From edbb7a97fb3b4dca76b38dbb68d189e2ebce5109 Mon Sep 17 00:00:00 2001 From: Walter Bright Date: Wed, 1 Nov 2023 22:30:32 -0700 Subject: [PATCH 001/215] dsymbol.d: replace some casts (dlang/dmd!15761) --- dmd/dsymbol.d | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/dmd/dsymbol.d b/dmd/dsymbol.d index 54f67c44129..914213c1e57 100644 --- a/dmd/dsymbol.d +++ b/dmd/dsymbol.d @@ -1725,8 +1725,8 @@ public: Parameters* p = new Parameter(STC.in_, Type.tchar.constOf().arrayOf(), null, null); parameters.push(p); Type tret = null; - tfgetmembers = new TypeFunction(parameters, tret, VarArg.none, LINK.d); - tfgetmembers = cast(TypeFunction)tfgetmembers.dsymbolSemantic(Loc.initial, &sc); + TypeFunction tf = new TypeFunction(parameters, tret, VarArg.none, LINK.d); + tfgetmembers = tf.dsymbolSemantic(Loc.initial, &sc).isTypeFunction(); } if (fdx) fdx = fdx.overloadExactMatch(tfgetmembers); @@ -1854,11 +1854,11 @@ extern (C++) final class WithScopeSymbol : ScopeDsymbol Expression eold = null; for (Expression e = withstate.exp; e && e != eold; e = resolveAliasThis(_scope, e, true)) { - if (e.op == EXP.scope_) + if (auto se = e.isScopeExp()) { - s = (cast(ScopeExp)e).sds; + s = se.sds; } - else if (e.op == EXP.type) + else if (e.isTypeExp()) { s = e.type.toDsymbol(null); } @@ -2032,11 +2032,11 @@ extern (C++) final class ArrayScopeSymbol : ScopeDsymbol if (TemplateDeclaration td = s.isTemplateDeclaration()) { dinteger_t dim = 0; - if (exp.op == EXP.array) + if (auto ae = exp.isArrayExp()) { - dim = (cast(ArrayExp)exp).currentDimension; + dim = ae.currentDimension; } - else if (exp.op == EXP.slice) + else if (exp.isSliceExp()) { dim = 0; // slices are currently always one-dimensional } @@ -2057,7 +2057,8 @@ extern (C++) final class ArrayScopeSymbol : ScopeDsymbol * Note that it's impossible to have both template & function opDollar, * because both take no arguments. */ - if (exp.op == EXP.array && (cast(ArrayExp)exp).arguments.length != 1) + auto ae = exp.isArrayExp(); + if (ae && ae.arguments.length != 1) { error(exp.loc, "`%s` only defines opDollar for one dimension", ad.toChars()); return null; From 89908778418bfdaa0bdef48b83070542c2b79d56 Mon Sep 17 00:00:00 2001 From: Walter Bright Date: Wed, 1 Nov 2023 23:56:30 -0700 Subject: [PATCH 002/215] fix Issue 24094 - importC __declspec not working in front of declaration statement (dlang/dmd!15773) --- dmd/cparse.d | 1 + tests/dmd/compilable/cattributes.i | 8 ++++++++ 2 files changed, 9 insertions(+) diff --git a/dmd/cparse.d b/dmd/cparse.d index 0b738cdc3d5..b8e80527ec7 100644 --- a/dmd/cparse.d +++ b/dmd/cparse.d @@ -328,6 +328,7 @@ final class CParser(AST) : Parser!AST case TOK._Atomic: case TOK.__attribute__: + case TOK.__declspec: Ldeclaration: { diff --git a/tests/dmd/compilable/cattributes.i b/tests/dmd/compilable/cattributes.i index 0f255b1ee01..0de97e3e30a 100644 --- a/tests/dmd/compilable/cattributes.i +++ b/tests/dmd/compilable/cattributes.i @@ -29,3 +29,11 @@ int testx(int a, int b, int c, int d, int e, int f) { return a + b + c + d + e + f + abcx + defx() + ghix() + jklx; } + +/*****************************************/ + +// https://issues.dlang.org/show_bug.cgi?id=24094 + +void test24094() { + __declspec(align(16)) short data[64]; +} From 63c83173365bfd26db045b3925a167479ed1c1dd Mon Sep 17 00:00:00 2001 From: RazvanN7 Date: Wed, 1 Nov 2023 17:59:18 +0200 Subject: [PATCH 003/215] Pull toLvalue out of expression.d --- dmd/expression.d | 252 +----------------------------------------- dmd/expression.h | 28 +---- dmd/expressionsem.d | 262 ++++++++++++++++++++++++++++++++++++++++++++ dmd/frontend.h | 27 +---- dmd/inline.d | 1 + 5 files changed, 270 insertions(+), 300 deletions(-) diff --git a/dmd/expression.d b/dmd/expression.d index 87611f4690f..cb5191b1dcf 100644 --- a/dmd/expression.d +++ b/dmd/expression.d @@ -678,25 +678,6 @@ extern (C++) abstract class Expression : ASTNode return false; } - /******************************* - * Give error if we're not an lvalue. - * If we can, convert expression to be an lvalue. - */ - Expression toLvalue(Scope* sc, Expression e) - { - if (!e) - e = this; - else if (!loc.isValid()) - loc = e.loc; - - if (e.op == EXP.type) - error(loc, "`%s` is a `%s` definition and cannot be modified", e.type.toChars(), e.type.kind()); - else - error(loc, "`%s` is not an lvalue and cannot be modified", e.toChars()); - - return ErrorExp.get(); - } - Expression modifiableLvalue(Scope* sc, Expression e) { //printf("Expression::modifiableLvalue() %s, type = %s\n", toChars(), type.toChars()); @@ -731,7 +712,7 @@ extern (C++) abstract class Expression : ASTNode return ErrorExp.get(); } } - return toLvalue(sc, e); + return this.toLvalue(sc, e); } /**************************************** @@ -1587,16 +1568,6 @@ extern (C++) final class IntegerExp : Expression return typeof(return)(r); } - override Expression toLvalue(Scope* sc, Expression e) - { - if (!e) - e = this; - else if (!loc.isValid()) - loc = e.loc; - error(e.loc, "cannot modify constant `%s`", e.toChars()); - return ErrorExp.get(); - } - override void accept(Visitor v) { v.visit(this); @@ -1745,11 +1716,6 @@ extern (C++) final class ErrorExp : Expression return errorexp; } - override Expression toLvalue(Scope* sc, Expression e) - { - return this; - } - override void accept(Visitor v) { v.visit(this); @@ -1987,11 +1953,6 @@ extern (C++) class IdentifierExp : Expression return true; } - override final Expression toLvalue(Scope* sc, Expression e) - { - return this; - } - override void accept(Visitor v) { v.visit(this); @@ -2036,11 +1997,6 @@ extern (C++) final class DsymbolExp : Expression return true; } - override Expression toLvalue(Scope* sc, Expression e) - { - return this; - } - override void accept(Visitor v) { v.visit(this); @@ -2087,16 +2043,6 @@ extern (C++) class ThisExp : Expression return type.toBasetype().ty != Tclass; } - override final Expression toLvalue(Scope* sc, Expression e) - { - if (type.toBasetype().ty == Tclass) - { - // Class `this` is an rvalue; struct `this` is an lvalue. - return Expression.toLvalue(sc, e); - } - return this; - } - override void accept(Visitor v) { v.visit(this); @@ -2464,12 +2410,6 @@ extern (C++) final class StringExp : Expression return (type && type.toBasetype().ty == Tsarray); } - override Expression toLvalue(Scope* sc, Expression e) - { - //printf("StringExp::toLvalue(%s) type = %s\n", toChars(), type ? type.toChars() : NULL); - return (type && type.toBasetype().ty == Tsarray) ? this : Expression.toLvalue(sc, e); - } - override Expression modifiableLvalue(Scope* sc, Expression e) { error(loc, "cannot modify string literal `%s`", toChars()); @@ -3050,14 +2990,6 @@ extern (C++) final class StructLiteralExp : Expression return -1; } - override Expression toLvalue(Scope* sc, Expression e) - { - if (sc.flags & SCOPE.Cfile) - return this; // C struct literals are lvalues - else - return Expression.toLvalue(sc, e); - } - override void accept(Visitor v) { v.visit(this); @@ -3203,15 +3135,6 @@ extern (C++) final class TemplateExp : Expression return fd !is null; } - override Expression toLvalue(Scope* sc, Expression e) - { - if (!fd) - return Expression.toLvalue(sc, e); - - assert(sc); - return symbolToExp(fd, loc, sc, true); - } - override bool checkType() { error(loc, "%s `%s` has no type", td.kind(), toChars()); @@ -3409,31 +3332,6 @@ extern (C++) final class VarExp : SymbolExp return true; } - override Expression toLvalue(Scope* sc, Expression e) - { - if (var.storage_class & STC.manifest) - { - error(loc, "manifest constant `%s` cannot be modified", var.toChars()); - return ErrorExp.get(); - } - if (var.storage_class & STC.lazy_ && !delegateWasExtracted) - { - error(loc, "lazy variable `%s` cannot be modified", var.toChars()); - return ErrorExp.get(); - } - if (var.ident == Id.ctfe) - { - error(loc, "cannot modify compiler-generated variable `__ctfe`"); - return ErrorExp.get(); - } - if (var.ident == Id.dollar) // https://issues.dlang.org/show_bug.cgi?id=13574 - { - error(loc, "cannot modify operator `$`"); - return ErrorExp.get(); - } - return this; - } - override Expression modifiableLvalue(Scope* sc, Expression e) { //printf("VarExp::modifiableLvalue('%s')\n", var.toChars()); @@ -3472,11 +3370,6 @@ extern (C++) final class OverExp : Expression return true; } - override Expression toLvalue(Scope* sc, Expression e) - { - return this; - } - override void accept(Visitor v) { v.visit(this); @@ -3936,16 +3829,10 @@ extern (C++) class BinAssignExp : BinExp return true; } - override final Expression toLvalue(Scope* sc, Expression ex) - { - // Lvalue-ness will be handled in glue layer. - return this; - } - override final Expression modifiableLvalue(Scope* sc, Expression e) { // should check e1.checkModifiable() ? - return toLvalue(sc, this); + return this.toLvalue(sc, this); } override void accept(Visitor v) @@ -4156,46 +4043,6 @@ extern (C++) final class DotVarExp : UnaExp return !(vd && vd.isField()); } - override Expression toLvalue(Scope* sc, Expression e) - { - //printf("DotVarExp::toLvalue(%s)\n", toChars()); - if (sc && sc.flags & SCOPE.Cfile) - { - /* C11 6.5.2.3-3: A postfix expression followed by the '.' or '->' operator - * is an lvalue if the first expression is an lvalue. - */ - if (!e1.isLvalue()) - return Expression.toLvalue(sc, e); - } - if (!isLvalue()) - return Expression.toLvalue(sc, e); - if (e1.op == EXP.this_ && sc.ctorflow.fieldinit.length && !(sc.ctorflow.callSuper & CSX.any_ctor)) - { - if (VarDeclaration vd = var.isVarDeclaration()) - { - auto ad = vd.isMember2(); - if (ad && ad.fields.length == sc.ctorflow.fieldinit.length) - { - foreach (i, f; ad.fields) - { - if (f == vd) - { - if (!(sc.ctorflow.fieldinit[i].csx & CSX.this_ctor)) - { - /* If the address of vd is taken, assume it is thereby initialized - * https://issues.dlang.org/show_bug.cgi?id=15869 - */ - modifyFieldVar(loc, sc, vd, e1); - } - break; - } - } - } - } - } - return this; - } - override Expression modifiableLvalue(Scope* sc, Expression e) { version (none) @@ -4486,13 +4333,6 @@ extern (C++) final class CallExp : UnaExp return false; } - override Expression toLvalue(Scope* sc, Expression e) - { - if (isLvalue()) - return this; - return Expression.toLvalue(sc, e); - } - override void accept(Visitor v) { v.visit(this); @@ -4600,11 +4440,6 @@ extern (C++) final class PtrExp : UnaExp return true; } - override Expression toLvalue(Scope* sc, Expression e) - { - return this; - } - override Expression modifiableLvalue(Scope* sc, Expression e) { //printf("PtrExp::modifiableLvalue() %s, type %s\n", toChars(), type.toChars()); @@ -4755,19 +4590,6 @@ extern (C++) final class CastExp : UnaExp e1.type.mutableOf().unSharedOf().equals(to.mutableOf().unSharedOf()); } - override Expression toLvalue(Scope* sc, Expression e) - { - if (sc && sc.flags & SCOPE.Cfile) - { - /* C11 6.5.4-5: A cast does not yield an lvalue. - */ - return Expression.toLvalue(sc, e); - } - if (isLvalue()) - return this; - return Expression.toLvalue(sc, e); - } - override void accept(Visitor v) { v.visit(this); @@ -4822,12 +4644,6 @@ extern (C++) final class VectorArrayExp : UnaExp return e1.isLvalue(); } - override Expression toLvalue(Scope* sc, Expression e) - { - e1 = e1.toLvalue(sc, e); - return this; - } - override void accept(Visitor v) { v.visit(this); @@ -4885,12 +4701,6 @@ extern (C++) final class SliceExp : UnaExp return (type && type.toBasetype().ty == Tsarray); } - override Expression toLvalue(Scope* sc, Expression e) - { - //printf("SliceExp::toLvalue(%s) type = %s\n", toChars(), type ? type.toChars() : NULL); - return (type && type.toBasetype().ty == Tsarray) ? this : Expression.toLvalue(sc, e); - } - override Expression modifiableLvalue(Scope* sc, Expression e) { error(loc, "slice expression `%s` is not a modifiable lvalue", toChars()); @@ -4964,13 +4774,6 @@ extern (C++) final class ArrayExp : UnaExp return true; } - override Expression toLvalue(Scope* sc, Expression e) - { - if (type && type.toBasetype().ty == Tvoid) - error(loc, "`void`s have no value"); - return this; - } - override void accept(Visitor v) { v.visit(this); @@ -5018,12 +4821,6 @@ extern (C++) final class CommaExp : BinExp return e2.isLvalue(); } - override Expression toLvalue(Scope* sc, Expression e) - { - e2 = e2.toLvalue(sc, null); - return this; - } - override Expression modifiableLvalue(Scope* sc, Expression e) { e2 = e2.modifiableLvalue(sc, e); @@ -5105,12 +4902,6 @@ extern (C++) final class DelegatePtrExp : UnaExp return e1.isLvalue(); } - override Expression toLvalue(Scope* sc, Expression e) - { - e1 = e1.toLvalue(sc, e); - return this; - } - override Expression modifiableLvalue(Scope* sc, Expression e) { if (sc.setUnsafe(false, this.loc, "cannot modify delegate pointer in `@safe` code `%s`", this)) @@ -5143,12 +4934,6 @@ extern (C++) final class DelegateFuncptrExp : UnaExp return e1.isLvalue(); } - override Expression toLvalue(Scope* sc, Expression e) - { - e1 = e1.toLvalue(sc, e); - return this; - } - override Expression modifiableLvalue(Scope* sc, Expression e) { if (sc.setUnsafe(false, this.loc, "cannot modify delegate function pointer in `@safe` code `%s`", this)) @@ -5205,13 +4990,6 @@ extern (C++) final class IndexExp : BinExp return true; } - override Expression toLvalue(Scope* sc, Expression e) - { - if (isLvalue()) - return this; - return Expression.toLvalue(sc, e); - } - override Expression modifiableLvalue(Scope* sc, Expression e) { //printf("IndexExp::modifiableLvalue(%s)\n", toChars()); @@ -5324,20 +5102,6 @@ extern (C++) class AssignExp : BinExp return true; } - override final Expression toLvalue(Scope* sc, Expression ex) - { - if (e1.op == EXP.slice || e1.op == EXP.arrayLength) - { - return Expression.toLvalue(sc, ex); - } - - /* In front-end level, AssignExp should make an lvalue of e1. - * Taking the address of e1 will be handled in low level layer, - * so this function does nothing. - */ - return this; - } - override void accept(Visitor v) { v.visit(this); @@ -6074,16 +5838,6 @@ extern (C++) final class CondExp : BinExp return e1.isLvalue() && e2.isLvalue(); } - override Expression toLvalue(Scope* sc, Expression ex) - { - // convert (econd ? e1 : e2) to *(econd ? &e1 : &e2) - CondExp e = cast(CondExp)copy(); - e.e1 = e1.toLvalue(sc, null).addressOf(); - e.e2 = e2.toLvalue(sc, null).addressOf(); - e.type = type.pointerTo(); - return new PtrExp(loc, e, type); - } - override Expression modifiableLvalue(Scope* sc, Expression e) { if (!e1.isLvalue() && !e2.isLvalue()) @@ -6093,7 +5847,7 @@ extern (C++) final class CondExp : BinExp } e1 = e1.modifiableLvalue(sc, e1); e2 = e2.modifiableLvalue(sc, e2); - return toLvalue(sc, this); + return this.toLvalue(sc, this); } override void accept(Visitor v) diff --git a/dmd/expression.h b/dmd/expression.h index f7f6b0b63ff..ddf606b1ce5 100644 --- a/dmd/expression.h +++ b/dmd/expression.h @@ -51,6 +51,7 @@ Expression *ctfeInterpret(Expression *e); void expandTuples(Expressions *exps, Identifiers *names = nullptr); StringExp *toUTF8(StringExp *se, Scope *sc); MATCH implicitConvTo(Expression *e, Type *t); +Expression *toLvalue(Expression *_this, Scope *sc, Expression *e); typedef unsigned char OwnedBy; enum @@ -99,7 +100,6 @@ class Expression : public ASTNode 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(); @@ -244,7 +244,6 @@ class IntegerExp final : public Expression real_t toImaginary() override; complex_t toComplex() override; Optional toBool() override; - Expression *toLvalue(Scope *sc, Expression *e) override; void accept(Visitor *v) override { v->visit(this); } dinteger_t getInteger() { return value; } template @@ -254,7 +253,6 @@ class IntegerExp final : public Expression 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 @@ class IdentifierExp : public Expression 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 @@ class DsymbolExp final : public Expression 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 @@ class ThisExp : public Expression ThisExp *syntaxCopy() override; Optional 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,7 +365,6 @@ class StringExp final : public Expression StringExp *toStringExp() override; Optional 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; @@ -469,7 +463,6 @@ class StructLiteralExp final : public Expression 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 +494,6 @@ class TemplateExp final : public Expression 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,7 +567,6 @@ class VarExp final : public SymbolExp 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 +580,6 @@ class OverExp final : public Expression OverloadSet *vars; bool isLvalue() override; - Expression *toLvalue(Scope *sc, Expression *e) override; void accept(Visitor *v) override { v->visit(this); } }; @@ -701,7 +691,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,7 +756,6 @@ class DotVarExp final : public UnaExp 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 +809,6 @@ class CallExp final : public UnaExp CallExp *syntaxCopy() override; bool isLvalue() override; - Expression *toLvalue(Scope *sc, Expression *e) override; void accept(Visitor *v) override { v->visit(this); } }; @@ -836,7 +823,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 +868,6 @@ class CastExp final : public UnaExp CastExp *syntaxCopy() override; bool isLvalue() override; - Expression *toLvalue(Scope *sc, Expression *e) override; void accept(Visitor *v) override { v->visit(this); } }; @@ -903,7 +888,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,7 +910,6 @@ class SliceExp final : public UnaExp public: SliceExp *syntaxCopy() override; bool isLvalue() override; - Expression *toLvalue(Scope *sc, Expression *e) override; Expression *modifiableLvalue(Scope *sc, Expression *e) override; Optional toBool() override; @@ -953,7 +936,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,7 +944,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 +959,6 @@ class ArrayExp final : public UnaExp ArrayExp *syntaxCopy() override; bool isLvalue() override; - Expression *toLvalue(Scope *sc, Expression *e) override; void accept(Visitor *v) override { v->visit(this); } }; @@ -997,7 +977,6 @@ class CommaExp final : public BinExp d_bool isGenerated; d_bool allowCommaExp; bool isLvalue() override; - Expression *toLvalue(Scope *sc, Expression *e) override; Expression *modifiableLvalue(Scope *sc, Expression *e) override; Optional toBool() override; void accept(Visitor *v) override { v->visit(this); } @@ -1012,7 +991,6 @@ class IndexExp final : public BinExp 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 +1025,6 @@ class AssignExp : public BinExp MemorySet memset; bool isLvalue() override final; - Expression *toLvalue(Scope *sc, Expression *ex) override final; void accept(Visitor *v) override { v->visit(this); } }; @@ -1292,7 +1269,6 @@ class CondExp final : public BinExp 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); } diff --git a/dmd/expressionsem.d b/dmd/expressionsem.d index 1ddb2b1ea08..c8616f73a51 100644 --- a/dmd/expressionsem.d +++ b/dmd/expressionsem.d @@ -14567,6 +14567,268 @@ Expression addDtorHook(Expression e, Scope* sc) } } +/******************************* +* Give error if we're not an lvalue. +* If we can, convert expression to be an lvalue. +*/ +extern(C++) Expression toLvalue(Expression _this, Scope* sc, Expression e) +{ + Expression visit(Expression _this) + { + // BinaryAssignExp does not have an EXP associated + // so it's treated on the default path. + // Lvalue-ness will be handled in glue :layer. + if (_this.isBinAssignExp()) + return _this; + if (!e) + e = _this; + else if (!_this.loc.isValid()) + _this.loc = e.loc; + + if (e.op == EXP.type) + error(_this.loc, "`%s` is a `%s` definition and cannot be modified", e.type.toChars(), e.type.kind()); + else + error(_this.loc, "`%s` is not an lvalue and cannot be modified", e.toChars()); + + return ErrorExp.get(); + } + + Expression visitInteger(IntegerExp _this) + { + if (!e) + e = _this; + else if (!_this.loc.isValid()) + _this.loc = e.loc; + error(e.loc, "cannot modify constant `%s`", e.toChars()); + return ErrorExp.get(); + } + + Expression visitThis(ThisExp _this) + { + if (_this.type.toBasetype().ty == Tclass) + { + // Class `this` is an rvalue; struct `this` is an lvalue. + return visit(_this); + } + + return _this; + } + + Expression visitString(StringExp _this) + { + //printf("StringExp::toLvalue(%s) type = %s\n", _this.toChars(), _this.type ? _this.type.toChars() : NULL); + return (_this.type && _this.type.toBasetype().ty == Tsarray) ? _this : visit(_this); + } + + Expression visitStructLiteral(StructLiteralExp _this) + { + if (sc.flags & SCOPE.Cfile) + return _this; // C struct literals are lvalues + else + return visit(_this); + } + + Expression visitTemplate(TemplateExp _this) + { + if (!_this.fd) + return visit(_this); + + assert(sc); + return symbolToExp(_this.fd, _this.loc, sc, true); + + } + + Expression visitVar(VarExp _this) + { + auto var = _this.var; + if (var.storage_class & STC.manifest) + { + error(_this.loc, "manifest constant `%s` cannot be modified", var.toChars()); + return ErrorExp.get(); + } + if (var.storage_class & STC.lazy_ && !_this.delegateWasExtracted) + { + error(_this.loc, "lazy variable `%s` cannot be modified", var.toChars()); + return ErrorExp.get(); + } + if (var.ident == Id.ctfe) + { + error(_this.loc, "cannot modify compiler-generated variable `__ctfe`"); + return ErrorExp.get(); + } + if (var.ident == Id.dollar) // https://issues.dlang.org/show_bug.cgi?id=13574 + { + error(_this.loc, "cannot modify operator `$`"); + return ErrorExp.get(); + } + return _this; + } + + Expression visitDotVar(DotVarExp _this) + { + auto e1 = _this.e1; + auto var = _this.var; + //printf("DotVarExp::toLvalue(%s)\n", toChars()); + if (sc && sc.flags & SCOPE.Cfile) + { + /* C11 6.5.2.3-3: A postfix expression followed by the '.' or '->' operator + * is an lvalue if the first expression is an lvalue. + */ + if (!e1.isLvalue()) + return visit(_this); + } + if (!_this.isLvalue()) + return visit(_this); + if (e1.op == EXP.this_ && sc.ctorflow.fieldinit.length && !(sc.ctorflow.callSuper & CSX.any_ctor)) + { + if (VarDeclaration vd = var.isVarDeclaration()) + { + auto ad = vd.isMember2(); + if (ad && ad.fields.length == sc.ctorflow.fieldinit.length) + { + foreach (i, f; ad.fields) + { + if (f == vd) + { + if (!(sc.ctorflow.fieldinit[i].csx & CSX.this_ctor)) + { + /* If the address of vd is taken, assume it is thereby initialized + * https://issues.dlang.org/show_bug.cgi?id=15869 + */ + modifyFieldVar(_this.loc, sc, vd, e1); + } + break; + } + } + } + } + } + return _this; + } + + Expression visitCall(CallExp _this) + { + if (_this.isLvalue()) + return _this; + return visit(_this); + } + + Expression visitCast(CastExp _this) + { + if (sc && sc.flags & SCOPE.Cfile) + { + /* C11 6.5.4-5: A cast does not yield an lvalue. + */ + return visit(_this); + } + if (_this.isLvalue()) + return _this; + return visit(_this); + } + + Expression visitVectorArray(VectorArrayExp _this) + { + _this.e1 = _this.e1.toLvalue(sc, e); + return _this; + } + + Expression visitSlice(SliceExp _this) + { + //printf("SliceExp::toLvalue(%s) _this.type = %s\n", _this.toChars(), _this.type ? _this.type.toChars() : NULL); + return (_this.type && _this.type.toBasetype().ty == Tsarray) ? _this : visit(_this); + } + + Expression visitArray(ArrayExp _this) + { + if (_this.type && _this.type.toBasetype().ty == Tvoid) + error(_this.loc, "`void`s have no value"); + return _this; + } + + Expression visitComma(CommaExp _this) + { + _this.e2 = _this.e2.toLvalue(sc, null); + return _this; + } + + Expression visitDelegatePointer(DelegatePtrExp _this) + { + _this.e1 = _this.e1.toLvalue(sc, e); + return _this; + } + + Expression visitDelegateFuncptr(DelegateFuncptrExp _this) + { + _this.e1 = _this.e1.toLvalue(sc, e); + return _this; + } + + Expression visitIndex(IndexExp _this) + { + if (_this.isLvalue()) + return _this; + return visit(_this); + } + + Expression visitAssign(AssignExp _this) + { + if (_this.e1.op == EXP.slice || _this.e1.op == EXP.arrayLength) + { + return visit(_this); + } + + /* In front-end level, AssignExp should make an lvalue of e1. + * Taking the address of e1 will be handled in low level layer, + * so this function does nothing. + */ + return _this; + } + + Expression visitCond(CondExp _this) + { + // convert (econd ? e1 : e2) to *(econd ? &e1 : &e2) + CondExp e = cast(CondExp)(_this.copy()); + e.e1 = _this.e1.toLvalue(sc, null).addressOf(); + e.e2 = _this.e2.toLvalue(sc, null).addressOf(); + e.type = _this.type.pointerTo(); + return new PtrExp(_this.loc, e, _this.type); + + } + + switch(_this.op) + { + default: return visit(_this); + + case EXP.int64: return visitInteger(_this.isIntegerExp()); + case EXP.error: return _this; + case EXP.identifier: return _this; + case EXP.dSymbol: return _this; + case EXP.this_: return visitThis(_this.isThisExp()); + case EXP.super_: return visitThis(_this.isSuperExp()); + case EXP.string_: return visitString(_this.isStringExp()); + case EXP.structLiteral: return visitStructLiteral(_this.isStructLiteralExp()); + case EXP.template_: return visitTemplate(_this.isTemplateExp()); + case EXP.variable: return visitVar(_this.isVarExp()); + case EXP.overloadSet: return _this; + case EXP.dotVariable: return visitDotVar(_this.isDotVarExp()); + case EXP.call: return visitCall(_this.isCallExp()); + case EXP.star: return _this; + case EXP.cast_: return visitCast(_this.isCastExp()); + case EXP.vectorArray: return visitVectorArray(_this.isVectorArrayExp()); + case EXP.slice: return visitSlice(_this.isSliceExp()); + case EXP.array: return visitArray(_this.isArrayExp()); + case EXP.comma: return visitComma(_this.isCommaExp()); + case EXP.delegatePointer: return visitDelegatePointer(_this.isDelegatePtrExp()); + case EXP.delegateFunctionPointer: return visitDelegateFuncptr(_this.isDelegateFuncptrExp()); + case EXP.index: return visitIndex(_this.isIndexExp()); + case EXP.construct: return visitAssign(_this.isConstructExp()); + case EXP.loweredAssignExp: return visitAssign(_this.isLoweredAssignExp()); + case EXP.blit: return visitAssign(_this.isBlitExp()); + case EXP.assign: return visitAssign(_this.isAssignExp()); + case EXP.question: return visitCond(_this.isCondExp()); + } +} + /**************************************************** * Determine if `exp`, which gets its address taken, can do so safely. * Params: diff --git a/dmd/frontend.h b/dmd/frontend.h index 1ce33a7abdd..484ae1e3e0b 100644 --- a/dmd/frontend.h +++ b/dmd/frontend.h @@ -967,7 +967,6 @@ class Expression : public ASTNode 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(); @@ -7031,7 +7030,6 @@ class IntegerExp final : public Expression _d_real toImaginary() override; complex_t toComplex() override; Optional toBool() override; - Expression* toLvalue(Scope* sc, Expression* e) override; void accept(Visitor* v) override; dinteger_t getInteger(); IntegerExp* syntaxCopy() override; @@ -7042,7 +7040,6 @@ class ErrorExp final : public Expression { public: static ErrorExp* get(); - Expression* toLvalue(Scope* sc, Expression* e) override; void accept(Visitor* v) override; static ErrorExp* errorexp; }; @@ -7093,7 +7090,6 @@ class IdentifierExp : public Expression bool parens; static IdentifierExp* create(const Loc& loc, Identifier* ident); bool isLvalue() final override; - Expression* toLvalue(Scope* sc, Expression* e) final override; void accept(Visitor* v) override; }; @@ -7109,7 +7105,6 @@ class DsymbolExp final : public Expression Dsymbol* s; bool hasOverloads; bool isLvalue() override; - Expression* toLvalue(Scope* sc, Expression* e) override; void accept(Visitor* v) override; }; @@ -7121,7 +7116,6 @@ class ThisExp : public Expression ThisExp* syntaxCopy() override; Optional toBool() override; bool isLvalue() final override; - Expression* toLvalue(Scope* sc, Expression* e) final override; void accept(Visitor* v) override; }; @@ -7167,7 +7161,6 @@ class StringExp final : public Expression int32_t compare(const StringExp* const se2) const; Optional toBool() override; bool isLvalue() override; - Expression* toLvalue(Scope* sc, Expression* e) override; Expression* modifiableLvalue(Scope* sc, Expression* e) override; void accept(Visitor* v) override; }; @@ -7231,7 +7224,6 @@ class StructLiteralExp final : public Expression static StructLiteralExp* create(const Loc& loc, StructDeclaration* sd, void* elements, Type* stype = nullptr); bool equals(const RootObject* const o) const override; StructLiteralExp* syntaxCopy() override; - Expression* toLvalue(Scope* sc, Expression* e) override; void accept(Visitor* v) override; }; @@ -7268,7 +7260,6 @@ class TemplateExp final : public Expression TemplateDeclaration* td; FuncDeclaration* fd; bool isLvalue() override; - Expression* toLvalue(Scope* sc, Expression* e) override; bool checkType() override; bool checkValue() override; void accept(Visitor* v) override; @@ -7325,7 +7316,6 @@ class VarExp final : public SymbolExp 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; }; @@ -7335,7 +7325,6 @@ class OverExp final : public Expression public: OverloadSet* vars; bool isLvalue() override; - Expression* toLvalue(Scope* sc, Expression* e) override; void accept(Visitor* v) override; }; @@ -7424,7 +7413,6 @@ class BinAssignExp : public BinExp { public: bool isLvalue() final override; - Expression* toLvalue(Scope* sc, Expression* ex) final override; Expression* modifiableLvalue(Scope* sc, Expression* e) final override; void accept(Visitor* v) override; }; @@ -7485,7 +7473,6 @@ class DotVarExp final : public UnaExp Declaration* var; bool hasOverloads; bool isLvalue() override; - Expression* toLvalue(Scope* sc, Expression* e) override; Expression* modifiableLvalue(Scope* sc, Expression* e) override; void accept(Visitor* v) override; }; @@ -7533,7 +7520,6 @@ class CallExp final : public UnaExp static CallExp* create(const Loc& loc, FuncDeclaration* fd, Expression* earg1); CallExp* syntaxCopy() override; bool isLvalue() override; - Expression* toLvalue(Scope* sc, Expression* e) override; void accept(Visitor* v) override; }; @@ -7547,7 +7533,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; }; @@ -7590,7 +7575,6 @@ class CastExp final : public UnaExp uint8_t mod; CastExp* syntaxCopy() override; bool isLvalue() override; - Expression* toLvalue(Scope* sc, Expression* e) override; void accept(Visitor* v) override; }; @@ -7609,7 +7593,6 @@ class VectorArrayExp final : public UnaExp { public: bool isLvalue() override; - Expression* toLvalue(Scope* sc, Expression* e) override; void accept(Visitor* v) override; }; @@ -7630,7 +7613,6 @@ class SliceExp final : public UnaExp public: SliceExp* syntaxCopy() override; bool isLvalue() override; - Expression* toLvalue(Scope* sc, Expression* e) override; Expression* modifiableLvalue(Scope* sc, Expression* e) override; Optional toBool() override; void accept(Visitor* v) override; @@ -7650,7 +7632,6 @@ class ArrayExp final : public UnaExp VarDeclaration* lengthVar; ArrayExp* syntaxCopy() override; bool isLvalue() override; - Expression* toLvalue(Scope* sc, Expression* e) override; void accept(Visitor* v) override; }; @@ -7666,7 +7647,6 @@ class CommaExp final : public BinExp const bool isGenerated; bool allowCommaExp; bool isLvalue() override; - Expression* toLvalue(Scope* sc, Expression* e) override; Expression* modifiableLvalue(Scope* sc, Expression* e) override; Optional toBool() override; void accept(Visitor* v) override; @@ -7686,7 +7666,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; }; @@ -7695,7 +7674,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; }; @@ -7708,7 +7686,6 @@ class IndexExp final : public BinExp bool indexIsInBounds; 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; }; @@ -7731,7 +7708,6 @@ class AssignExp : public BinExp MemorySet memset; AssignExp(const Loc& loc, EXP tok, Expression* e1, Expression* e2); bool isLvalue() final override; - Expression* toLvalue(Scope* sc, Expression* ex) final override; void accept(Visitor* v) override; }; @@ -7967,7 +7943,6 @@ class CondExp final : public BinExp Expression* econd; CondExp* syntaxCopy() override; bool isLvalue() override; - Expression* toLvalue(Scope* sc, Expression* ex) override; Expression* modifiableLvalue(Scope* sc, Expression* e) override; void accept(Visitor* v) override; }; @@ -8034,6 +8009,8 @@ extern Expression* resolveProperties(Scope* sc, Expression* e); extern Expression* expressionSemantic(Expression* e, Scope* sc); +extern Expression* toLvalue(Expression* _this, Scope* sc, Expression* e); + extern const char* toChars(const Initializer* const i); extern void json_generate(Array& modules, OutBuffer& buf); diff --git a/dmd/inline.d b/dmd/inline.d index ab74bff78d1..9ac3a1644d9 100644 --- a/dmd/inline.d +++ b/dmd/inline.d @@ -2187,6 +2187,7 @@ private void expandInline(Loc callLoc, FuncDeclaration fd, FuncDeclaration paren auto e = doInlineAs!Expression(fd.fbody, ids); fd.inlineNest--; + import dmd.expressionsem : toLvalue; // https://issues.dlang.org/show_bug.cgi?id=11322 if (tf.isref) e = e.toLvalue(null, null); From bea4866d195c2eec56b8c72e6f587005452b2a28 Mon Sep 17 00:00:00 2001 From: Razvan Nitu Date: Fri, 3 Nov 2023 00:33:26 +0200 Subject: [PATCH 004/215] Pull out check* from expression.Expression + move them to expressionsem + make most of them private (dlang/dmd!15775) --- dmd/canthrow.d | 3 +- dmd/expression.d | 411 --------------------------------------- dmd/expressionsem.d | 460 +++++++++++++++++++++++++++++++++++++++++--- dmd/typesem.d | 2 +- 4 files changed, 434 insertions(+), 442 deletions(-) diff --git a/dmd/canthrow.d b/dmd/canthrow.d index 8aece3bdd71..67305922df6 100644 --- a/dmd/canthrow.d +++ b/dmd/canthrow.d @@ -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) { diff --git a/dmd/expression.d b/dmd/expression.d index cb5191b1dcf..b384809c192 100644 --- a/dmd/expression.d +++ b/dmd/expression.d @@ -816,417 +816,6 @@ extern (C++) abstract class Expression : ASTNode return checkValue(); } - extern (D) final bool checkDeprecated(Scope* sc, Dsymbol s) - { - return s.checkDeprecated(loc, sc); - } - - extern (D) final bool checkDisabled(Scope* sc, Dsymbol s) - { - if (auto d = s.isDeclaration()) - { - return d.checkDisabled(loc, sc); - } - - return false; - } - - /********************************************* - * Calling function f. - * Check the purity, i.e. if we're in a pure function - * we can only call other pure functions. - * Returns true if error occurs. - */ - extern (D) final bool checkPurity(Scope* sc, FuncDeclaration f) - { - if (!sc.func) - return false; - if (sc.func == f) - return false; - if (sc.intypeof == 1) - return false; - if (sc.flags & (SCOPE.ctfe | SCOPE.debug_)) - return false; - - // If the call has a pure parent, then the called func must be pure. - if (!f.isPure() && checkImpure(sc, loc, null, f)) - { - error(loc, "`pure` %s `%s` cannot call impure %s `%s`", - sc.func.kind(), sc.func.toPrettyChars(), f.kind(), - f.toPrettyChars()); - - if (!f.isDtorDeclaration()) - errorSupplementalInferredAttr(f, /*max depth*/ 10, /*deprecation*/ false, STC.pure_); - - checkOverriddenDtor(sc, f, dd => dd.type.toTypeFunction().purity != PURE.impure, "impure"); - return true; - } - return false; - } - - /** - * Checks whether `f` is a generated `DtorDeclaration` that hides a user-defined one - * which passes `check` while `f` doesn't (e.g. when the user defined dtor is pure but - * the generated dtor is not). - * In that case the method will identify and print all members causing the attribute - * missmatch. - * - * Params: - * sc = scope - * f = potential `DtorDeclaration` - * check = current check (e.g. whether it's pure) - * checkName = the kind of check (e.g. `"pure"`) - */ - extern (D) final void checkOverriddenDtor(Scope* sc, FuncDeclaration f, - scope bool function(DtorDeclaration) check, const string checkName - ) { - auto dd = f.isDtorDeclaration(); - if (!dd || !dd.isGenerated()) - return; - - // DtorDeclaration without parents should fail at an earlier stage - auto ad = cast(AggregateDeclaration) f.toParent2(); - assert(ad); - - if (ad.userDtors.length) - { - if (!check(ad.userDtors[0])) // doesn't match check (e.g. is impure as well) - return; - - // Sanity check - assert(!check(ad.fieldDtor)); - } - - dd.loc.errorSupplemental("%s`%s.~this` is %.*s because of the following field's destructors:", - dd.isGenerated() ? "generated " : "".ptr, - ad.toChars, - cast(int) checkName.length, checkName.ptr); - - // Search for the offending fields - foreach (field; ad.fields) - { - // Only structs may define automatically called destructors - auto ts = field.type.isTypeStruct(); - if (!ts) - { - // But they might be part of a static array - auto ta = field.type.isTypeSArray(); - if (!ta) - continue; - - ts = ta.baseElemOf().isTypeStruct(); - if (!ts) - continue; - } - - auto fieldSym = ts.toDsymbol(sc); - assert(fieldSym); // Resolving ts must succeed because missing defs. should error before - - auto fieldSd = fieldSym.isStructDeclaration(); - assert(fieldSd); // ts is a TypeStruct, this would imply a malformed ASR - - if (fieldSd.dtor && !check(fieldSd.dtor)) - { - field.loc.errorSupplemental(" - %s %s", field.type.toChars(), field.toChars()); - - if (fieldSd.dtor.isGenerated()) - checkOverriddenDtor(sc, fieldSd.dtor, check, checkName); - else - fieldSd.dtor.loc.errorSupplemental(" %.*s `%s.~this` is declared here", - cast(int) checkName.length, checkName.ptr, fieldSd.toChars()); - } - } - } - - /******************************************* - * Accessing variable v. - * Check for purity and safety violations. - * Returns true if error occurs. - */ - extern (D) final bool checkPurity(Scope* sc, VarDeclaration v) - { - //printf("v = %s %s\n", v.type.toChars(), v.toChars()); - /* Look for purity and safety violations when accessing variable v - * from current function. - */ - if (!sc.func) - return false; - if (sc.intypeof == 1) - return false; // allow violations inside typeof(expression) - if (sc.flags & (SCOPE.ctfe | SCOPE.debug_)) - return false; // allow violations inside compile-time evaluated expressions and debug conditionals - if (v.ident == Id.ctfe) - return false; // magic variable never violates pure and safe - if (v.isImmutable()) - return false; // always safe and pure to access immutables... - if (v.isConst() && !v.isReference() && (v.isDataseg() || v.isParameter()) && v.type.implicitConvTo(v.type.immutableOf())) - return false; // or const global/parameter values which have no mutable indirections - if (v.storage_class & STC.manifest) - return false; // ...or manifest constants - - // accessing empty structs is pure - // https://issues.dlang.org/show_bug.cgi?id=18694 - // https://issues.dlang.org/show_bug.cgi?id=21464 - // https://issues.dlang.org/show_bug.cgi?id=23589 - if (v.type.ty == Tstruct) - { - StructDeclaration sd = (cast(TypeStruct)v.type).sym; - if (sd.members) // not opaque - { - if (sd.semanticRun >= PASS.semanticdone) - sd.determineSize(v.loc); - if (sd.hasNoFields) - return false; - } - } - - bool err = false; - if (v.isDataseg()) - { - // https://issues.dlang.org/show_bug.cgi?id=7533 - // Accessing implicit generated __gate is pure. - if (v.ident == Id.gate) - return false; - - if (checkImpure(sc, loc, "`pure` %s `%s` cannot access mutable static data `%s`", v)) - { - error(loc, "`pure` %s `%s` cannot access mutable static data `%s`", - sc.func.kind(), sc.func.toPrettyChars(), v.toChars()); - err = true; - } - } - else - { - /* Given: - * void f() { - * int fx; - * pure void g() { - * int gx; - * /+pure+/ void h() { - * int hx; - * /+pure+/ void i() { } - * } - * } - * } - * i() can modify hx and gx but not fx - */ - - Dsymbol vparent = v.toParent2(); - for (Dsymbol s = sc.func; !err && s; s = s.toParentP(vparent)) - { - if (s == vparent) - break; - - if (AggregateDeclaration ad = s.isAggregateDeclaration()) - { - if (ad.isNested()) - continue; - break; - } - FuncDeclaration ff = s.isFuncDeclaration(); - if (!ff) - break; - if (ff.isNested() || ff.isThis()) - { - if (ff.type.isImmutable() || - ff.type.isShared() && !MODimplicitConv(ff.type.mod, v.type.mod)) - { - OutBuffer ffbuf; - OutBuffer vbuf; - MODMatchToBuffer(&ffbuf, ff.type.mod, v.type.mod); - MODMatchToBuffer(&vbuf, v.type.mod, ff.type.mod); - error(loc, "%s%s `%s` cannot access %sdata `%s`", - ffbuf.peekChars(), ff.kind(), ff.toPrettyChars(), vbuf.peekChars(), v.toChars()); - err = true; - break; - } - continue; - } - break; - } - } - - /* Do not allow safe functions to access __gshared data - */ - if (v.storage_class & STC.gshared) - { - if (sc.setUnsafe(false, this.loc, - "`@safe` function `%s` cannot access `__gshared` data `%s`", sc.func, v)) - { - err = true; - } - } - - return err; - } - - /* - Check if sc.func is impure or can be made impure. - Returns true on error, i.e. if sc.func is pure and cannot be made impure. - */ - private static bool checkImpure(Scope* sc, Loc loc, const(char)* fmt, RootObject arg0) - { - return sc.func && (isRootTraitsCompilesScope(sc) - ? sc.func.isPureBypassingInference() >= PURE.weak - : sc.func.setImpure(loc, fmt, arg0)); - } - - /********************************************* - * Calling function f. - * Check the safety, i.e. if we're in a @safe function - * we can only call @safe or @trusted functions. - * Returns true if error occurs. - */ - extern (D) final bool checkSafety(Scope* sc, FuncDeclaration f) - { - if (sc.func == f) - return false; - if (sc.intypeof == 1) - return false; - if (sc.flags & SCOPE.debug_) - return false; - if ((sc.flags & SCOPE.ctfe) && sc.func) - return false; - - if (!sc.func) - { - if (sc.varDecl && !f.safetyInprocess && !f.isSafe() && !f.isTrusted()) - { - if (sc.varDecl.storage_class & STC.safe) - { - error(loc, "`@safe` variable `%s` cannot be initialized by calling `@system` function `%s`", - sc.varDecl.toChars(), f.toChars()); - return true; - } - else - { - sc.varDecl.storage_class |= STC.system; - sc.varDecl.systemInferred = true; - } - } - return false; - } - - if (!f.isSafe() && !f.isTrusted()) - { - if (isRootTraitsCompilesScope(sc) ? sc.func.isSafeBypassingInference() : sc.func.setUnsafeCall(f)) - { - if (!loc.isValid()) // e.g. implicitly generated dtor - loc = sc.func.loc; - - const prettyChars = f.toPrettyChars(); - error(loc, "`@safe` %s `%s` cannot call `@system` %s `%s`", - sc.func.kind(), sc.func.toPrettyChars(), f.kind(), - prettyChars); - if (!f.isDtorDeclaration) - errorSupplementalInferredAttr(f, /*max depth*/ 10, /*deprecation*/ false, STC.safe); - .errorSupplemental(f.loc, "`%s` is declared here", prettyChars); - - checkOverriddenDtor(sc, f, dd => dd.type.toTypeFunction().trust > TRUST.system, "@system"); - - return true; - } - } - else if (f.isSafe() && f.safetyViolation) - { - // for dip1000 by default transition, print deprecations for calling functions that will become `@system` - if (sc.func.isSafeBypassingInference()) - { - .deprecation(this.loc, "`@safe` function `%s` calling `%s`", sc.func.toChars(), f.toChars()); - errorSupplementalInferredAttr(f, 10, true, STC.safe); - } - else if (!sc.func.safetyViolation) - { - import dmd.func : AttributeViolation; - sc.func.safetyViolation = new AttributeViolation(this.loc, null, f, null, null); - } - } - return false; - } - - /********************************************* - * Calling function f. - * Check the @nogc-ness, i.e. if we're in a @nogc function - * we can only call other @nogc functions. - * Returns true if error occurs. - */ - extern (D) final bool checkNogc(Scope* sc, FuncDeclaration f) - { - if (!sc.func) - return false; - if (sc.func == f) - return false; - if (sc.intypeof == 1) - return false; - if (sc.flags & (SCOPE.ctfe | SCOPE.debug_)) - return false; - /* The original expressions (`new S(...)` or `new S[...]``) will be - * verified instead. This is to keep errors related to the original code - * and not the lowering. - */ - if (f.ident == Id._d_newitemT || f.ident == Id._d_newarrayT) - return false; - - if (!f.isNogc()) - { - if (isRootTraitsCompilesScope(sc) ? sc.func.isNogcBypassingInference() : sc.func.setGCCall(f)) - { - if (loc.linnum == 0) // e.g. implicitly generated dtor - loc = sc.func.loc; - - // Lowered non-@nogc'd hooks will print their own error message inside of nogc.d (NOGCVisitor.visit(CallExp e)), - // so don't print anything to avoid double error messages. - if (!(f.ident == Id._d_HookTraceImpl || f.ident == Id._d_arraysetlengthT - || f.ident == Id._d_arrayappendT || f.ident == Id._d_arrayappendcTX - || f.ident == Id._d_arraycatnTX || f.ident == Id._d_newclassT)) - { - error(loc, "`@nogc` %s `%s` cannot call non-@nogc %s `%s`", - sc.func.kind(), sc.func.toPrettyChars(), f.kind(), f.toPrettyChars()); - - if (!f.isDtorDeclaration) - f.errorSupplementalInferredAttr(/*max depth*/ 10, /*deprecation*/ false, STC.nogc); - } - - checkOverriddenDtor(sc, f, dd => dd.type.toTypeFunction().isnogc, "non-@nogc"); - - return true; - } - } - return false; - } - - /******************************************** - * Check that the postblit is callable if t is an array of structs. - * Returns true if error happens. - */ - extern (D) final bool checkPostblit(Scope* sc, Type t) - { - if (auto ts = t.baseElemOf().isTypeStruct()) - { - if (global.params.useTypeInfo && Type.dtypeinfo) - { - // https://issues.dlang.org/show_bug.cgi?id=11395 - // Require TypeInfo generation for array concatenation - semanticTypeInfo(sc, t); - } - - StructDeclaration sd = ts.sym; - if (sd.postblit) - { - if (sd.postblit.checkDisabled(loc, sc)) - return true; - - //checkDeprecated(sc, sd.postblit); // necessary? - checkPurity(sc, sd.postblit); - checkSafety(sc, sd.postblit); - checkNogc(sc, sd.postblit); - //checkAccess(sd, loc, sc, sd.postblit); // necessary? - return false; - } - } - return false; - } - /******************************* * Check whether the expression allows RMW operations, error with rmw operator diagnostic if not. * ex is the RHS expression, or NULL if ++/-- is used (for diagnostics) diff --git a/dmd/expressionsem.d b/dmd/expressionsem.d index c8616f73a51..6bcaf7826cc 100644 --- a/dmd/expressionsem.d +++ b/dmd/expressionsem.d @@ -1731,6 +1731,403 @@ private bool haveSameThis(FuncDeclaration outerFunc, FuncDeclaration calledFunc) return false; } +/********************************************* + * Calling function f. + * Check the purity, i.e. if we're in a pure function + * we can only call other pure functions. + * Returns true if error occurs. + */ +private bool checkPurity(FuncDeclaration f, const ref Loc loc, Scope* sc) +{ + if (!sc.func) + return false; + if (sc.func == f) + return false; + if (sc.intypeof == 1) + return false; + if (sc.flags & (SCOPE.ctfe | SCOPE.debug_)) + return false; + + // If the call has a pure parent, then the called func must be pure. + if (!f.isPure() && checkImpure(sc, loc, null, f)) + { + error(loc, "`pure` %s `%s` cannot call impure %s `%s`", + sc.func.kind(), sc.func.toPrettyChars(), f.kind(), + f.toPrettyChars()); + + if (!f.isDtorDeclaration()) + errorSupplementalInferredAttr(f, /*max depth*/ 10, /*deprecation*/ false, STC.pure_); + + f.checkOverriddenDtor(sc, loc, dd => dd.type.toTypeFunction().purity != PURE.impure, "impure"); + return true; + } + return false; +} + +/** + * Checks whether `f` is a generated `DtorDeclaration` that hides a user-defined one + * which passes `check` while `f` doesn't (e.g. when the user defined dtor is pure but + * the generated dtor is not). + * In that case the method will identify and print all members causing the attribute + * missmatch. + * + * Params: + * f = potential `DtorDeclaration` + * sc = scope + * loc = location + * check = current check (e.g. whether it's pure) + * checkName = the kind of check (e.g. `"pure"`) + */ +void checkOverriddenDtor(FuncDeclaration f, Scope* sc, const ref Loc loc, + scope bool function(DtorDeclaration) check, const string checkName) +{ + auto dd = f.isDtorDeclaration(); + if (!dd || !dd.isGenerated()) + return; + + // DtorDeclaration without parents should fail at an earlier stage + auto ad = cast(AggregateDeclaration) f.toParent2(); + assert(ad); + + if (ad.userDtors.length) + { + if (!check(ad.userDtors[0])) // doesn't match check (e.g. is impure as well) + return; + + // Sanity check + assert(!check(ad.fieldDtor)); + } + + dd.loc.errorSupplemental("%s`%s.~this` is %.*s because of the following field's destructors:", + dd.isGenerated() ? "generated " : "".ptr, + ad.toChars, + cast(int) checkName.length, checkName.ptr); + + // Search for the offending fields + foreach (field; ad.fields) + { + // Only structs may define automatically called destructors + auto ts = field.type.isTypeStruct(); + if (!ts) + { + // But they might be part of a static array + auto ta = field.type.isTypeSArray(); + if (!ta) + continue; + + ts = ta.baseElemOf().isTypeStruct(); + if (!ts) + continue; + } + + auto fieldSym = ts.toDsymbol(sc); + assert(fieldSym); // Resolving ts must succeed because missing defs. should error before + + auto fieldSd = fieldSym.isStructDeclaration(); + assert(fieldSd); // ts is a TypeStruct, this would imply a malformed ASR + + if (fieldSd.dtor && !check(fieldSd.dtor)) + { + field.loc.errorSupplemental(" - %s %s", field.type.toChars(), field.toChars()); + + if (fieldSd.dtor.isGenerated()) + fieldSd.dtor.checkOverriddenDtor(sc, loc, check, checkName); + else + fieldSd.dtor.loc.errorSupplemental(" %.*s `%s.~this` is declared here", + cast(int) checkName.length, checkName.ptr, fieldSd.toChars()); + } + } +} + +/******************************************* + * Accessing variable v. + * Check for purity and safety violations. + * Returns true if error occurs. + */ +private bool checkPurity(VarDeclaration v, const ref Loc loc, Scope* sc) +{ + //printf("v = %s %s\n", v.type.toChars(), v.toChars()); + /* Look for purity and safety violations when accessing variable v + * from current function. + */ + if (!sc.func) + return false; + if (sc.intypeof == 1) + return false; // allow violations inside typeof(expression) + if (sc.flags & (SCOPE.ctfe | SCOPE.debug_)) + return false; // allow violations inside compile-time evaluated expressions and debug conditionals + if (v.ident == Id.ctfe) + return false; // magic variable never violates pure and safe + if (v.isImmutable()) + return false; // always safe and pure to access immutables... + if (v.isConst() && !v.isReference() && (v.isDataseg() || v.isParameter()) && v.type.implicitConvTo(v.type.immutableOf())) + return false; // or const global/parameter values which have no mutable indirections + if (v.storage_class & STC.manifest) + return false; // ...or manifest constants + + // accessing empty structs is pure + // https://issues.dlang.org/show_bug.cgi?id=18694 + // https://issues.dlang.org/show_bug.cgi?id=21464 + // https://issues.dlang.org/show_bug.cgi?id=23589 + if (v.type.ty == Tstruct) + { + StructDeclaration sd = (cast(TypeStruct)v.type).sym; + if (sd.members) // not opaque + { + if (sd.semanticRun >= PASS.semanticdone) + sd.determineSize(v.loc); + if (sd.hasNoFields) + return false; + } + } + + bool err = false; + if (v.isDataseg()) + { + // https://issues.dlang.org/show_bug.cgi?id=7533 + // Accessing implicit generated __gate is pure. + if (v.ident == Id.gate) + return false; + + if (checkImpure(sc, loc, "`pure` %s `%s` cannot access mutable static data `%s`", v)) + { + error(loc, "`pure` %s `%s` cannot access mutable static data `%s`", + sc.func.kind(), sc.func.toPrettyChars(), v.toChars()); + err = true; + } + } + else + { + /* Given: + * void f() { + * int fx; + * pure void g() { + * int gx; + * /+pure+/ void h() { + * int hx; + * /+pure+/ void i() { } + * } + * } + * } + * i() can modify hx and gx but not fx + */ + + Dsymbol vparent = v.toParent2(); + for (Dsymbol s = sc.func; !err && s; s = s.toParentP(vparent)) + { + if (s == vparent) + break; + + if (AggregateDeclaration ad = s.isAggregateDeclaration()) + { + if (ad.isNested()) + continue; + break; + } + FuncDeclaration ff = s.isFuncDeclaration(); + if (!ff) + break; + if (ff.isNested() || ff.isThis()) + { + if (ff.type.isImmutable() || + ff.type.isShared() && !MODimplicitConv(ff.type.mod, v.type.mod)) + { + OutBuffer ffbuf; + OutBuffer vbuf; + MODMatchToBuffer(&ffbuf, ff.type.mod, v.type.mod); + MODMatchToBuffer(&vbuf, v.type.mod, ff.type.mod); + error(loc, "%s%s `%s` cannot access %sdata `%s`", + ffbuf.peekChars(), ff.kind(), ff.toPrettyChars(), vbuf.peekChars(), v.toChars()); + err = true; + break; + } + continue; + } + break; + } + } + + /* Do not allow safe functions to access __gshared data + */ + if (v.storage_class & STC.gshared) + { + if (sc.setUnsafe(false, loc, + "`@safe` function `%s` cannot access `__gshared` data `%s`", sc.func, v)) + { + err = true; + } + } + + return err; +} + +/* +Check if sc.func is impure or can be made impure. +Returns true on error, i.e. if sc.func is pure and cannot be made impure. +*/ +private bool checkImpure(Scope* sc, Loc loc, const(char)* fmt, RootObject arg0) +{ + return sc.func && (isRootTraitsCompilesScope(sc) + ? sc.func.isPureBypassingInference() >= PURE.weak + : sc.func.setImpure(loc, fmt, arg0)); +} + +/********************************************* + * Calling function f. + * Check the safety, i.e. if we're in a @safe function + * we can only call @safe or @trusted functions. + * Returns true if error occurs. + */ +private bool checkSafety(FuncDeclaration f, ref Loc loc, Scope* sc) +{ + if (sc.func == f) + return false; + if (sc.intypeof == 1) + return false; + if (sc.flags & SCOPE.debug_) + return false; + if ((sc.flags & SCOPE.ctfe) && sc.func) + return false; + + if (!sc.func) + { + if (sc.varDecl && !f.safetyInprocess && !f.isSafe() && !f.isTrusted()) + { + if (sc.varDecl.storage_class & STC.safe) + { + error(loc, "`@safe` variable `%s` cannot be initialized by calling `@system` function `%s`", + sc.varDecl.toChars(), f.toChars()); + return true; + } + else + { + sc.varDecl.storage_class |= STC.system; + sc.varDecl.systemInferred = true; + } + } + return false; + } + + if (!f.isSafe() && !f.isTrusted()) + { + if (isRootTraitsCompilesScope(sc) ? sc.func.isSafeBypassingInference() : sc.func.setUnsafeCall(f)) + { + if (!loc.isValid()) // e.g. implicitly generated dtor + loc = sc.func.loc; + + const prettyChars = f.toPrettyChars(); + error(loc, "`@safe` %s `%s` cannot call `@system` %s `%s`", + sc.func.kind(), sc.func.toPrettyChars(), f.kind(), + prettyChars); + if (!f.isDtorDeclaration) + errorSupplementalInferredAttr(f, /*max depth*/ 10, /*deprecation*/ false, STC.safe); + .errorSupplemental(f.loc, "`%s` is declared here", prettyChars); + + f.checkOverriddenDtor(sc, loc, dd => dd.type.toTypeFunction().trust > TRUST.system, "@system"); + + return true; + } + } + else if (f.isSafe() && f.safetyViolation) + { + // for dip1000 by default transition, print deprecations for calling functions that will become `@system` + if (sc.func.isSafeBypassingInference()) + { + .deprecation(loc, "`@safe` function `%s` calling `%s`", sc.func.toChars(), f.toChars()); + errorSupplementalInferredAttr(f, 10, true, STC.safe); + } + else if (!sc.func.safetyViolation) + { + import dmd.func : AttributeViolation; + sc.func.safetyViolation = new AttributeViolation(loc, null, f, null, null); + } + } + return false; +} + +/********************************************* + * Calling function f. + * Check the @nogc-ness, i.e. if we're in a @nogc function + * we can only call other @nogc functions. + * Returns true if error occurs. + */ +private bool checkNogc(FuncDeclaration f, ref Loc loc, Scope* sc) +{ + if (!sc.func) + return false; + if (sc.func == f) + return false; + if (sc.intypeof == 1) + return false; + if (sc.flags & (SCOPE.ctfe | SCOPE.debug_)) + return false; + /* The original expressions (`new S(...)` or `new S[...]``) will be + * verified instead. This is to keep errors related to the original code + * and not the lowering. + */ + if (f.ident == Id._d_newitemT || f.ident == Id._d_newarrayT) + return false; + + if (!f.isNogc()) + { + if (isRootTraitsCompilesScope(sc) ? sc.func.isNogcBypassingInference() : sc.func.setGCCall(f)) + { + if (loc.linnum == 0) // e.g. implicitly generated dtor + loc = sc.func.loc; + + // Lowered non-@nogc'd hooks will print their own error message inside of nogc.d (NOGCVisitor.visit(CallExp e)), + // so don't print anything to avoid double error messages. + if (!(f.ident == Id._d_HookTraceImpl || f.ident == Id._d_arraysetlengthT + || f.ident == Id._d_arrayappendT || f.ident == Id._d_arrayappendcTX + || f.ident == Id._d_arraycatnTX || f.ident == Id._d_newclassT)) + { + error(loc, "`@nogc` %s `%s` cannot call non-@nogc %s `%s`", + sc.func.kind(), sc.func.toPrettyChars(), f.kind(), f.toPrettyChars()); + + if (!f.isDtorDeclaration) + f.errorSupplementalInferredAttr(/*max depth*/ 10, /*deprecation*/ false, STC.nogc); + } + + f.checkOverriddenDtor(sc, loc, dd => dd.type.toTypeFunction().isnogc, "non-@nogc"); + + return true; + } + } + return false; +} + +/******************************************** + * Check that the postblit is callable if t is an array of structs. + * Returns true if error happens. + */ +private bool checkPostblit(Type t, ref Loc loc, Scope* sc) +{ + if (auto ts = t.baseElemOf().isTypeStruct()) + { + if (global.params.useTypeInfo && Type.dtypeinfo) + { + // https://issues.dlang.org/show_bug.cgi?id=11395 + // Require TypeInfo generation for array concatenation + semanticTypeInfo(sc, t); + } + + StructDeclaration sd = ts.sym; + if (sd.postblit) + { + if (sd.postblit.checkDisabled(loc, sc)) + return true; + + //checkDeprecated(sc, sd.postblit); // necessary? + sd.postblit.checkPurity(loc, sc); + sd.postblit.checkSafety(loc, sc); + sd.postblit.checkNogc(loc, sc); + //checkAccess(sd, loc, sc, sd.postblit); // necessary? + return false; + } + } + return false; +} + /*************************************** * Pull out any properties. */ @@ -1942,7 +2339,7 @@ private Expression resolvePropertiesX(Scope* sc, Expression e1, Expression e2 = { if (auto v = ve.var.isVarDeclaration()) { - if (ve.checkPurity(sc, v)) + if (v.checkPurity(ve.loc, sc)) return ErrorExp.get(); } } @@ -5257,7 +5654,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor ve.type = t.typeSemantic(exp.loc, sc); } VarDeclaration v = ve.var.isVarDeclaration(); - if (v && ve.checkPurity(sc, v)) + if (v && v.checkPurity(ve.loc, sc)) return setError(); } @@ -5885,9 +6282,9 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor // Purity and safety check should run after testing arguments matching if (exp.f) { - exp.checkPurity(sc, exp.f); - exp.checkSafety(sc, exp.f); - exp.checkNogc(sc, exp.f); + exp.f.checkPurity(exp.loc, sc); + exp.f.checkSafety(exp.loc, sc); + exp.f.checkNogc(exp.loc, sc); if (exp.f.checkNestedReference(sc, exp.loc)) return setError(); } @@ -7934,7 +8331,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor if (!checkAddressVar(sc, exp.e1, v)) return setError(); - ve.checkPurity(sc, v); + v.checkPurity(ve.loc, sc); } FuncDeclaration f = ve.var.isFuncDeclaration(); if (f) @@ -8006,7 +8403,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor */ if (VarDeclaration v = expToVariable(exp.e1)) { - exp.e1.checkPurity(sc, v); + v.checkPurity(exp.e1.loc, sc); } } else if (wasCond) @@ -8306,9 +8703,9 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor if (cd.dtor) { err |= !cd.dtor.functionSemantic(); - err |= exp.checkPurity(sc, cd.dtor); - err |= exp.checkSafety(sc, cd.dtor); - err |= exp.checkNogc(sc, cd.dtor); + err |= cd.dtor.checkPurity(exp.loc, sc); + err |= cd.dtor.checkSafety(exp.loc, sc); + err |= cd.dtor.checkNogc(exp.loc, sc); } if (err) return setError(); @@ -10344,7 +10741,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor { if (exp.op != EXP.blit && (e2x.op == EXP.slice && (cast(UnaExp)e2x).e1.isLvalue() || e2x.op == EXP.cast_ && (cast(UnaExp)e2x).e1.isLvalue() || e2x.op != EXP.slice && e2x.isLvalue())) { - if (e1x.checkPostblit(sc, t1)) + if (t1.checkPostblit(e1x.loc, sc)) return setError(); } @@ -10587,7 +10984,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor // '= null' is the only allowable block assignment (Bug 7493) exp.memset = MemorySet.blockAssign; // make it easy for back end to tell what this is e2x = e2x.implicitCastTo(sc, t1.nextOf()); - if (exp.op != EXP.blit && e2x.isLvalue() && exp.e1.checkPostblit(sc, t1.nextOf())) + if (exp.op != EXP.blit && e2x.isLvalue() && t1.nextOf.checkPostblit(exp.e1.loc, sc)) return setError(); } else if (exp.e1.op == EXP.slice && @@ -10625,7 +11022,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor e2x.op == EXP.cast_ && (cast(UnaExp)e2x).e1.isLvalue() || e2x.op != EXP.slice && e2x.isLvalue())) { - if (exp.e1.checkPostblit(sc, t1.nextOf())) + if (t1.nextOf().checkPostblit(exp.e1.loc, sc)) return setError(); } @@ -11095,7 +11492,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor { // EXP.concatenateAssign assert(exp.op == EXP.concatenateAssign); - if (exp.e1.checkPostblit(sc, tb1next)) + if (tb1next.checkPostblit(exp.e1.loc, sc)) return setError(); exp.e2 = exp.e2.castTo(sc, exp.e1.type); @@ -11113,7 +11510,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor if (tb2.ty == Tclass && (cast(TypeClass)tb2).implicitConvToThroughAliasThis(tb1next)) goto Laliasthis; // Append element - if (exp.e2.checkPostblit(sc, tb2)) + if (tb2.checkPostblit(exp.e2.loc, sc)) return setError(); if (checkNewEscape(sc, exp.e2, false)) @@ -11746,7 +12143,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor } else { - if (exp.e2.checkPostblit(sc, tb2)) + if (tb2.checkPostblit(exp.e2.loc, sc)) return setError(); // Postblit call will be done in runtime helper function } @@ -11781,7 +12178,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor } else { - if (exp.e1.checkPostblit(sc, tb1)) + if (tb1.checkPostblit(exp.e1.loc, sc)) return setError(); } @@ -11836,7 +12233,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor } if (Type tbn = tb.nextOf()) { - if (exp.checkPostblit(sc, tbn)) + if (tbn.checkPostblit(exp.loc, sc)) return setError(); } Type t1 = exp.e1.type.toBasetype(); @@ -13582,6 +13979,14 @@ private Expression dotIdSemanticPropX(DotIdExp exp, Scope* sc) return exp; } +private bool checkDisabled(Dsymbol s, ref Loc loc, Scope* sc) +{ + if (auto d = s.isDeclaration()) + return d.checkDisabled(loc, sc); + + return false; +} + /****************************** * Resolve properties, i.e. `e1.ident`, without seeing UFCS. * Params: @@ -13675,8 +14080,8 @@ Expression dotIdSemanticProp(DotIdExp exp, Scope* sc, bool gag) // if 's' is a tuple variable, the tuple is returned. s = s.toAlias(); - exp.checkDeprecated(sc, s); - exp.checkDisabled(sc, s); + s.checkDeprecated(exp.loc, sc); + s.checkDisabled(exp.loc, sc); if (auto em = s.isEnumMember()) { @@ -14938,15 +15343,12 @@ bool checkAddressable(Expression e, Scope* sc) */ private bool checkFunctionAttributes(Expression exp, Scope* sc, FuncDeclaration f) { - with(exp) - { - bool error = checkDisabled(sc, f); - error |= checkDeprecated(sc, f); - error |= checkPurity(sc, f); - error |= checkSafety(sc, f); - error |= checkNogc(sc, f); - return error; - } + bool error = f.checkDisabled(exp.loc, sc); + error |= f.checkDeprecated(exp.loc, sc); + error |= f.checkPurity(exp.loc, sc); + error |= f.checkSafety(exp.loc, sc); + error |= f.checkNogc(exp.loc, sc); + return error; } /******************************* diff --git a/dmd/typesem.d b/dmd/typesem.d index bbe11f63d4b..4618a6754ae 100644 --- a/dmd/typesem.d +++ b/dmd/typesem.d @@ -3748,7 +3748,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()) From ca5da988fb4e4acfcbcd32c9f3fc04f3b11022b1 Mon Sep 17 00:00:00 2001 From: Paul Backus Date: Fri, 3 Nov 2023 09:17:37 -0400 Subject: [PATCH 005/215] Fix Issue 24224 - __traits(initSymbol) treats aggregate-derived enum as base type (dlang/dmd!15776) --- dmd/traits.d | 16 ++++++++++++---- tests/dmd/fail_compilation/fail24224.d | 22 ++++++++++++++++++++++ 2 files changed, 34 insertions(+), 4 deletions(-) create mode 100644 tests/dmd/fail_compilation/fail24224.d diff --git a/dmd/traits.d b/dmd/traits.d index ca2af79dde4..7489f99aa90 100644 --- a/dmd/traits.d +++ b/dmd/traits.d @@ -1875,16 +1875,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; diff --git a/tests/dmd/fail_compilation/fail24224.d b/tests/dmd/fail_compilation/fail24224.d new file mode 100644 index 00000000000..db87f5305d7 --- /dev/null +++ b/tests/dmd/fail_compilation/fail24224.d @@ -0,0 +1,22 @@ +/+ +TEST_OUTPUT: +--- +fail_compilation/fail24224.d(19): Error: struct / class type expected as argument to __traits(initSymbol) instead of `ES` +fail_compilation/fail24224.d(20): Error: struct / class type expected as argument to __traits(initSymbol) instead of `EU` +fail_compilation/fail24224.d(21): Error: struct / class type expected as argument to __traits(initSymbol) instead of `EC` +--- ++/ +struct S {} +union U {} +class C {} + +enum ES : S { a = S.init } +enum EU : U { a = U.init } +enum EC : C { a = C.init } + +void test() +{ + auto init1 = __traits(initSymbol, ES); + auto init2 = __traits(initSymbol, EU); + auto init3 = __traits(initSymbol, EC); +} From db566fc7a1fc4e18c5271461f1aa6db39a870d96 Mon Sep 17 00:00:00 2001 From: Iain Buclaw Date: Tue, 31 Oct 2023 06:02:20 +0100 Subject: [PATCH 006/215] test: Remove 'ref' checks from -preview=in tests --- tests/dmd/compilable/previewin.d | 6 ------ tests/dmd/runnable/previewin.d | 20 +++++++++----------- 2 files changed, 9 insertions(+), 17 deletions(-) diff --git a/tests/dmd/compilable/previewin.d b/tests/dmd/compilable/previewin.d index 8926fbd6aa7..558005c5280 100644 --- a/tests/dmd/compilable/previewin.d +++ b/tests/dmd/compilable/previewin.d @@ -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)); } } diff --git a/tests/dmd/runnable/previewin.d b/tests/dmd/runnable/previewin.d index 117070dfe5e..50f22ee22bf 100644 --- a/tests/dmd/runnable/previewin.d +++ b/tests/dmd/runnable/previewin.d @@ -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; } From 53b0b6b7ef8fa3f5abf35d5afc64fb1236ef68e3 Mon Sep 17 00:00:00 2001 From: RazvanN7 Date: Tue, 7 Nov 2023 08:58:16 +0200 Subject: [PATCH 007/215] Extract expression.modifiableLvalue and move it to expressionsem --- dmd/expression.d | 292 ------------------------------------------- dmd/expression.h | 13 +- dmd/expressionsem.d | 297 ++++++++++++++++++++++++++++++++++++++++++++ dmd/frontend.h | 14 +-- 4 files changed, 300 insertions(+), 316 deletions(-) diff --git a/dmd/expression.d b/dmd/expression.d index b384809c192..37ee9ea66cd 100644 --- a/dmd/expression.d +++ b/dmd/expression.d @@ -678,43 +678,6 @@ extern (C++) abstract class Expression : ASTNode return false; } - Expression modifiableLvalue(Scope* sc, Expression e) - { - //printf("Expression::modifiableLvalue() %s, type = %s\n", toChars(), type.toChars()); - // See if this expression is a modifiable lvalue (i.e. not const) - if (checkModifiable(this, sc) == Modifiable.yes) - { - assert(type); - if (!type.isMutable()) - { - if (auto dve = this.isDotVarExp()) - { - if (isNeedThisScope(sc, dve.var)) - for (Dsymbol s = sc.func; s; s = s.toParentLocal()) - { - FuncDeclaration ff = s.isFuncDeclaration(); - if (!ff) - break; - if (!ff.type.isMutable) - { - error(loc, "cannot modify `%s` in `%s` function", toChars(), MODtoChars(type.mod)); - return ErrorExp.get(); - } - } - } - error(loc, "cannot modify `%s` expression `%s`", MODtoChars(type.mod), toChars()); - return ErrorExp.get(); - } - else if (!type.isAssignable()) - { - error(loc, "cannot modify struct instance `%s` of type `%s` because it contains `const` or `immutable` members", - toChars(), type.toChars()); - return ErrorExp.get(); - } - } - return this.toLvalue(sc, e); - } - /**************************************** * Resolve __FILE__, __LINE__, __MODULE__, __FUNCTION__, __PRETTY_FUNCTION__, __FILE_FULL_PATH__ to loc. */ @@ -1999,12 +1962,6 @@ extern (C++) final class StringExp : Expression return (type && type.toBasetype().ty == Tsarray); } - override Expression modifiableLvalue(Scope* sc, Expression e) - { - error(loc, "cannot modify string literal `%s`", toChars()); - return ErrorExp.get(); - } - /******************************** * Convert string contents to a 0 terminated string, * allocated by mem.xmalloc(). @@ -2921,18 +2878,6 @@ extern (C++) final class VarExp : SymbolExp return true; } - override Expression modifiableLvalue(Scope* sc, Expression e) - { - //printf("VarExp::modifiableLvalue('%s')\n", var.toChars()); - if (var.storage_class & STC.manifest) - { - error(loc, "cannot modify manifest constant `%s`", toChars()); - return ErrorExp.get(); - } - // See if this expression is a modifiable lvalue (i.e. not const) - return Expression.modifiableLvalue(sc, e); - } - override void accept(Visitor v) { v.visit(this); @@ -3418,12 +3363,6 @@ extern (C++) class BinAssignExp : BinExp return true; } - override final Expression modifiableLvalue(Scope* sc, Expression e) - { - // should check e1.checkModifiable() ? - return this.toLvalue(sc, this); - } - override void accept(Visitor v) { v.visit(this); @@ -3632,18 +3571,6 @@ extern (C++) final class DotVarExp : UnaExp return !(vd && vd.isField()); } - override Expression modifiableLvalue(Scope* sc, Expression e) - { - version (none) - { - printf("DotVarExp::modifiableLvalue(%s)\n", toChars()); - printf("e1.type = %s\n", e1.type.toChars()); - printf("var.type = %s\n", var.type.toChars()); - } - - return Expression.modifiableLvalue(sc, e); - } - override void accept(Visitor v) { v.visit(this); @@ -4029,25 +3956,6 @@ extern (C++) final class PtrExp : UnaExp return true; } - override Expression modifiableLvalue(Scope* sc, Expression e) - { - //printf("PtrExp::modifiableLvalue() %s, type %s\n", toChars(), type.toChars()); - Declaration var; - if (auto se = e1.isSymOffExp()) - var = se.var; - else if (auto ve = e1.isVarExp()) - var = ve.var; - if (var && var.type.isFunction_Delegate_PtrToFunction()) - { - if (var.type.isTypeFunction()) - error(loc, "function `%s` is not an lvalue and cannot be modified", var.toChars()); - else - error(loc, "function pointed to by `%s` is not an lvalue and cannot be modified", var.toChars()); - return ErrorExp.get(); - } - return Expression.modifiableLvalue(sc, e); - } - override void accept(Visitor v) { v.visit(this); @@ -4290,12 +4198,6 @@ extern (C++) final class SliceExp : UnaExp return (type && type.toBasetype().ty == Tsarray); } - override Expression modifiableLvalue(Scope* sc, Expression e) - { - error(loc, "slice expression `%s` is not a modifiable lvalue", toChars()); - return this; - } - override Optional!bool toBool() { return e1.toBool(); @@ -4410,12 +4312,6 @@ extern (C++) final class CommaExp : BinExp return e2.isLvalue(); } - override Expression modifiableLvalue(Scope* sc, Expression e) - { - e2 = e2.modifiableLvalue(sc, e); - return this; - } - override Optional!bool toBool() { return e2.toBool(); @@ -4491,15 +4387,6 @@ extern (C++) final class DelegatePtrExp : UnaExp return e1.isLvalue(); } - override Expression modifiableLvalue(Scope* sc, Expression e) - { - if (sc.setUnsafe(false, this.loc, "cannot modify delegate pointer in `@safe` code `%s`", this)) - { - return ErrorExp.get(); - } - return Expression.modifiableLvalue(sc, e); - } - override void accept(Visitor v) { v.visit(this); @@ -4523,15 +4410,6 @@ extern (C++) final class DelegateFuncptrExp : UnaExp return e1.isLvalue(); } - override Expression modifiableLvalue(Scope* sc, Expression e) - { - if (sc.setUnsafe(false, this.loc, "cannot modify delegate function pointer in `@safe` code `%s`", this)) - { - return ErrorExp.get(); - } - return Expression.modifiableLvalue(sc, e); - } - override void accept(Visitor v) { v.visit(this); @@ -4579,16 +4457,6 @@ extern (C++) final class IndexExp : BinExp return true; } - override Expression modifiableLvalue(Scope* sc, Expression e) - { - //printf("IndexExp::modifiableLvalue(%s)\n", toChars()); - Expression ex = markSettingAAElem(); - if (ex.op == EXP.error) - return ex; - - return Expression.modifiableLvalue(sc, e); - } - extern (D) Expression markSettingAAElem() { if (e1.type.toBasetype().ty == Taarray) @@ -5427,18 +5295,6 @@ extern (C++) final class CondExp : BinExp return e1.isLvalue() && e2.isLvalue(); } - override Expression modifiableLvalue(Scope* sc, Expression e) - { - if (!e1.isLvalue() && !e2.isLvalue()) - { - error(loc, "conditional expression `%s` is not a modifiable lvalue", toChars()); - return ErrorExp.get(); - } - e1 = e1.modifiableLvalue(sc, e1); - e2 = e2.modifiableLvalue(sc, e2); - return this.toLvalue(sc, this); - } - override void accept(Visitor v) { v.visit(this); @@ -5673,154 +5529,6 @@ extern (C++) final class GenericExp : Expression } } -/*************************************** - * Parameters: - * sc: scope - * flag: 1: do not issue error message for invalid modification - 2: the exp is a DotVarExp and a subfield of the leftmost - variable is modified - * Returns: - * Whether the type is modifiable - */ -extern(D) Modifiable checkModifiable(Expression exp, Scope* sc, ModifyFlags flag = ModifyFlags.none) -{ - switch(exp.op) - { - case EXP.variable: - auto varExp = cast(VarExp)exp; - - //printf("VarExp::checkModifiable %s", varExp.toChars()); - assert(varExp.type); - return varExp.var.checkModify(varExp.loc, sc, null, flag); - - case EXP.dotVariable: - auto dotVarExp = cast(DotVarExp)exp; - - //printf("DotVarExp::checkModifiable %s %s\n", dotVarExp.toChars(), dotVarExp.type.toChars()); - if (dotVarExp.e1.op == EXP.this_) - return dotVarExp.var.checkModify(dotVarExp.loc, sc, dotVarExp.e1, flag); - - /* https://issues.dlang.org/show_bug.cgi?id=12764 - * If inside a constructor and an expression of type `this.field.var` - * is encountered, where `field` is a struct declaration with - * default construction disabled, we must make sure that - * assigning to `var` does not imply that `field` was initialized - */ - if (sc.func && sc.func.isCtorDeclaration()) - { - // if inside a constructor scope and e1 of this DotVarExp - // is another DotVarExp, then check if the leftmost expression is a `this` identifier - if (auto dve = dotVarExp.e1.isDotVarExp()) - { - // Iterate the chain of DotVarExp to find `this` - // Keep track whether access to fields was limited to union members - // s.t. one can initialize an entire struct inside nested unions - // (but not its members) - bool onlyUnion = true; - while (true) - { - auto v = dve.var.isVarDeclaration(); - assert(v); - - // Accessing union member? - auto t = v.type.isTypeStruct(); - if (!t || !t.sym.isUnionDeclaration()) - onlyUnion = false; - - // Another DotVarExp left? - if (!dve.e1 || dve.e1.op != EXP.dotVariable) - break; - - dve = cast(DotVarExp) dve.e1; - } - - if (dve.e1.op == EXP.this_) - { - scope v = dve.var.isVarDeclaration(); - /* if v is a struct member field with no initializer, no default construction - * and v wasn't intialized before - */ - if (v && v.isField() && !v._init && !v.ctorinit) - { - if (auto ts = v.type.isTypeStruct()) - { - if (ts.sym.noDefaultCtor) - { - /* checkModify will consider that this is an initialization - * of v while it is actually an assignment of a field of v - */ - scope modifyLevel = v.checkModify(dotVarExp.loc, sc, dve.e1, !onlyUnion ? (flag | ModifyFlags.fieldAssign) : flag); - if (modifyLevel == Modifiable.initialization) - { - // https://issues.dlang.org/show_bug.cgi?id=22118 - // v is a union type field that was assigned - // a variable, therefore it counts as initialization - if (v.ctorinit) - return Modifiable.initialization; - - return Modifiable.yes; - } - return modifyLevel; - } - } - } - } - } - } - - //printf("\te1 = %s\n", e1.toChars()); - return dotVarExp.e1.checkModifiable(sc, flag); - - case EXP.star: - auto ptrExp = cast(PtrExp)exp; - if (auto se = ptrExp.e1.isSymOffExp()) - { - return se.var.checkModify(ptrExp.loc, sc, null, flag); - } - else if (auto ae = ptrExp.e1.isAddrExp()) - { - return ae.e1.checkModifiable(sc, flag); - } - return Modifiable.yes; - - case EXP.slice: - auto sliceExp = cast(SliceExp)exp; - - //printf("SliceExp::checkModifiable %s\n", sliceExp.toChars()); - auto e1 = sliceExp.e1; - if (e1.type.ty == Tsarray || (e1.op == EXP.index && e1.type.ty != Tarray) || e1.op == EXP.slice) - { - return e1.checkModifiable(sc, flag); - } - return Modifiable.yes; - - case EXP.comma: - return (cast(CommaExp)exp).e2.checkModifiable(sc, flag); - - case EXP.index: - auto indexExp = cast(IndexExp)exp; - auto e1 = indexExp.e1; - if (e1.type.ty == Tsarray || - e1.type.ty == Taarray || - (e1.op == EXP.index && e1.type.ty != Tarray) || - e1.op == EXP.slice) - { - return e1.checkModifiable(sc, flag); - } - return Modifiable.yes; - - case EXP.question: - auto condExp = cast(CondExp)exp; - if (condExp.e1.checkModifiable(sc, flag) != Modifiable.no - && condExp.e2.checkModifiable(sc, flag) != Modifiable.no) - return Modifiable.yes; - return Modifiable.no; - - default: - return exp.type ? Modifiable.yes : Modifiable.no; // default modifiable - } -} - /** * Verify if the given identifier is _d_array{,set}ctor. * diff --git a/dmd/expression.h b/dmd/expression.h index ddf606b1ce5..ca3d021c9ec 100644 --- a/dmd/expression.h +++ b/dmd/expression.h @@ -52,6 +52,7 @@ void expandTuples(Expressions *exps, Identifiers *names = nullptr); StringExp *toUTF8(StringExp *se, Scope *sc); MATCH implicitConvTo(Expression *e, Type *t); Expression *toLvalue(Expression *_this, Scope *sc, Expression *e); +Expression *modifiableLvalue(Expression* exp, Scope *sc, Expression *e); typedef unsigned char OwnedBy; enum @@ -100,7 +101,6 @@ class Expression : public ASTNode virtual complex_t toComplex(); virtual StringExp *toStringExp(); virtual bool isLvalue(); - virtual Expression *modifiableLvalue(Scope *sc, Expression *e); virtual Expression *resolveLoc(const Loc &loc, Scope *sc); virtual bool checkType(); virtual bool checkValue(); @@ -365,7 +365,6 @@ class StringExp final : public Expression StringExp *toStringExp() override; Optional toBool() override; bool isLvalue() 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; @@ -567,7 +566,6 @@ class VarExp final : public SymbolExp static VarExp *create(const Loc &loc, Declaration *var, bool hasOverloads = true); bool equals(const RootObject * const o) const override; bool isLvalue() override; - Expression *modifiableLvalue(Scope *sc, Expression *e) override; void accept(Visitor *v) override { v->visit(this); } }; @@ -691,7 +689,6 @@ class BinAssignExp : public BinExp { public: bool isLvalue() override final; - Expression *modifiableLvalue(Scope *sc, Expression *e) override final; void accept(Visitor *v) override { v->visit(this); } }; @@ -756,7 +753,6 @@ class DotVarExp final : public UnaExp d_bool hasOverloads; bool isLvalue() override; - Expression *modifiableLvalue(Scope *sc, Expression *e) override; void accept(Visitor *v) override { v->visit(this); } }; @@ -823,7 +819,6 @@ class PtrExp final : public UnaExp { public: bool isLvalue() override; - Expression *modifiableLvalue(Scope *sc, Expression *e) override; void accept(Visitor *v) override { v->visit(this); } }; @@ -910,7 +905,6 @@ class SliceExp final : public UnaExp public: SliceExp *syntaxCopy() override; bool isLvalue() override; - Expression *modifiableLvalue(Scope *sc, Expression *e) override; Optional toBool() override; void accept(Visitor *v) override { v->visit(this); } @@ -936,7 +930,6 @@ class DelegatePtrExp final : public UnaExp { public: bool isLvalue() override; - Expression *modifiableLvalue(Scope *sc, Expression *e) override; void accept(Visitor *v) override { v->visit(this); } }; @@ -944,7 +937,6 @@ class DelegateFuncptrExp final : public UnaExp { public: bool isLvalue() override; - Expression *modifiableLvalue(Scope *sc, Expression *e) override; void accept(Visitor *v) override { v->visit(this); } }; @@ -977,7 +969,6 @@ class CommaExp final : public BinExp d_bool isGenerated; d_bool allowCommaExp; bool isLvalue() override; - Expression *modifiableLvalue(Scope *sc, Expression *e) override; Optional toBool() override; void accept(Visitor *v) override { v->visit(this); } }; @@ -991,7 +982,6 @@ class IndexExp final : public BinExp IndexExp *syntaxCopy() override; bool isLvalue() override; - Expression *modifiableLvalue(Scope *sc, Expression *e) override; void accept(Visitor *v) override { v->visit(this); } }; @@ -1269,7 +1259,6 @@ class CondExp final : public BinExp CondExp *syntaxCopy() override; bool isLvalue() override; - Expression *modifiableLvalue(Scope *sc, Expression *e) override; void accept(Visitor *v) override { v->visit(this); } }; diff --git a/dmd/expressionsem.d b/dmd/expressionsem.d index 6bcaf7826cc..3d2b3b01f19 100644 --- a/dmd/expressionsem.d +++ b/dmd/expressionsem.d @@ -15234,6 +15234,303 @@ extern(C++) Expression toLvalue(Expression _this, Scope* sc, Expression e) } } +/*************************************** + * Parameters: + * sc: scope + * flag: 1: do not issue error message for invalid modification + 2: the exp is a DotVarExp and a subfield of the leftmost + variable is modified + * Returns: + * Whether the type is modifiable + */ +Modifiable checkModifiable(Expression exp, Scope* sc, ModifyFlags flag = ModifyFlags.none) +{ + switch(exp.op) + { + case EXP.variable: + auto varExp = cast(VarExp)exp; + + //printf("VarExp::checkModifiable %s", varExp.toChars()); + assert(varExp.type); + return varExp.var.checkModify(varExp.loc, sc, null, flag); + + case EXP.dotVariable: + auto dotVarExp = cast(DotVarExp)exp; + + //printf("DotVarExp::checkModifiable %s %s\n", dotVarExp.toChars(), dotVarExp.type.toChars()); + if (dotVarExp.e1.op == EXP.this_) + return dotVarExp.var.checkModify(dotVarExp.loc, sc, dotVarExp.e1, flag); + + /* https://issues.dlang.org/show_bug.cgi?id=12764 + * If inside a constructor and an expression of type `this.field.var` + * is encountered, where `field` is a struct declaration with + * default construction disabled, we must make sure that + * assigning to `var` does not imply that `field` was initialized + */ + if (sc.func && sc.func.isCtorDeclaration()) + { + // if inside a constructor scope and e1 of this DotVarExp + // is another DotVarExp, then check if the leftmost expression is a `this` identifier + if (auto dve = dotVarExp.e1.isDotVarExp()) + { + // Iterate the chain of DotVarExp to find `this` + // Keep track whether access to fields was limited to union members + // s.t. one can initialize an entire struct inside nested unions + // (but not its members) + bool onlyUnion = true; + while (true) + { + auto v = dve.var.isVarDeclaration(); + assert(v); + + // Accessing union member? + auto t = v.type.isTypeStruct(); + if (!t || !t.sym.isUnionDeclaration()) + onlyUnion = false; + + // Another DotVarExp left? + if (!dve.e1 || dve.e1.op != EXP.dotVariable) + break; + + dve = cast(DotVarExp) dve.e1; + } + + if (dve.e1.op == EXP.this_) + { + scope v = dve.var.isVarDeclaration(); + /* if v is a struct member field with no initializer, no default construction + * and v wasn't intialized before + */ + if (v && v.isField() && !v._init && !v.ctorinit) + { + if (auto ts = v.type.isTypeStruct()) + { + if (ts.sym.noDefaultCtor) + { + /* checkModify will consider that this is an initialization + * of v while it is actually an assignment of a field of v + */ + scope modifyLevel = v.checkModify(dotVarExp.loc, sc, dve.e1, !onlyUnion ? (flag | ModifyFlags.fieldAssign) : flag); + if (modifyLevel == Modifiable.initialization) + { + // https://issues.dlang.org/show_bug.cgi?id=22118 + // v is a union type field that was assigned + // a variable, therefore it counts as initialization + if (v.ctorinit) + return Modifiable.initialization; + + return Modifiable.yes; + } + return modifyLevel; + } + } + } + } + } + } + + //printf("\te1 = %s\n", e1.toChars()); + return dotVarExp.e1.checkModifiable(sc, flag); + + case EXP.star: + auto ptrExp = cast(PtrExp)exp; + if (auto se = ptrExp.e1.isSymOffExp()) + { + return se.var.checkModify(ptrExp.loc, sc, null, flag); + } + else if (auto ae = ptrExp.e1.isAddrExp()) + { + return ae.e1.checkModifiable(sc, flag); + } + return Modifiable.yes; + + case EXP.slice: + auto sliceExp = cast(SliceExp)exp; + + //printf("SliceExp::checkModifiable %s\n", sliceExp.toChars()); + auto e1 = sliceExp.e1; + if (e1.type.ty == Tsarray || (e1.op == EXP.index && e1.type.ty != Tarray) || e1.op == EXP.slice) + { + return e1.checkModifiable(sc, flag); + } + return Modifiable.yes; + + case EXP.comma: + return (cast(CommaExp)exp).e2.checkModifiable(sc, flag); + + case EXP.index: + auto indexExp = cast(IndexExp)exp; + auto e1 = indexExp.e1; + if (e1.type.ty == Tsarray || + e1.type.ty == Taarray || + (e1.op == EXP.index && e1.type.ty != Tarray) || + e1.op == EXP.slice) + { + return e1.checkModifiable(sc, flag); + } + return Modifiable.yes; + + case EXP.question: + auto condExp = cast(CondExp)exp; + if (condExp.e1.checkModifiable(sc, flag) != Modifiable.no + && condExp.e2.checkModifiable(sc, flag) != Modifiable.no) + return Modifiable.yes; + return Modifiable.no; + + default: + return exp.type ? Modifiable.yes : Modifiable.no; // default modifiable + } +} + +extern(C++) Expression modifiableLvalue(Expression _this, Scope* sc, Expression e) +{ + Expression visit(Expression exp) + { + //printf("Expression::modifiableLvalue() %s, type = %s\n", exp.toChars(), exp.type.toChars()); + // See if this expression is a modifiable lvalue (i.e. not const) + if (exp.isBinAssignExp()) + return exp.toLvalue(sc, exp); + + auto type = exp.type; + if (checkModifiable(exp, sc) == Modifiable.yes) + { + assert(type); + if (!type.isMutable()) + { + if (auto dve = exp.isDotVarExp()) + { + if (isNeedThisScope(sc, dve.var)) + for (Dsymbol s = sc.func; s; s = s.toParentLocal()) + { + FuncDeclaration ff = s.isFuncDeclaration(); + if (!ff) + break; + if (!ff.type.isMutable) + { + error(exp.loc, "cannot modify `%s` in `%s` function", exp.toChars(), MODtoChars(type.mod)); + return ErrorExp.get(); + } + } + } + error(exp.loc, "cannot modify `%s` expression `%s`", MODtoChars(type.mod), exp.toChars()); + return ErrorExp.get(); + } + else if (!type.isAssignable()) + { + error(exp.loc, "cannot modify struct instance `%s` of type `%s` because it contains `const` or `immutable` members", + exp.toChars(), type.toChars()); + return ErrorExp.get(); + } + } + return exp.toLvalue(sc, e); + } + + Expression visitString(StringExp exp) + { + error(exp.loc, "cannot modify string literal `%s`", exp.toChars()); + return ErrorExp.get(); + } + + Expression visitVar(VarExp exp) + { + //printf("VarExp::modifiableLvalue('%s')\n", exp.var.toChars()); + if (exp.var.storage_class & STC.manifest) + { + error(exp.loc, "cannot modify manifest constant `%s`", exp.toChars()); + return ErrorExp.get(); + } + // See if this expression is a modifiable lvalue (i.e. not const) + return visit(exp); + } + + Expression visitPtr(PtrExp exp) + { + //printf("PtrExp::modifiableLvalue() %s, type %s\n", exp.toChars(), exp.type.toChars()); + Declaration var; + auto e1 = exp.e1; + if (auto se = e1.isSymOffExp()) + var = se.var; + else if (auto ve = e1.isVarExp()) + var = ve.var; + if (var && var.type.isFunction_Delegate_PtrToFunction()) + { + if (var.type.isTypeFunction()) + error(exp.loc, "function `%s` is not an lvalue and cannot be modified", var.toChars()); + else + error(exp.loc, "function pointed to by `%s` is not an lvalue and cannot be modified", var.toChars()); + return ErrorExp.get(); + } + return visit(exp); + } + + Expression visitSlice(SliceExp exp) + { + error(exp.loc, "slice expression `%s` is not a modifiable lvalue", exp.toChars()); + return exp; + } + + Expression visitComma(CommaExp exp) + { + exp.e2 = exp.e2.modifiableLvalue(sc, e); + return exp; + } + + Expression visitDelegatePtr(DelegatePtrExp exp) + { + if (sc.setUnsafe(false, exp.loc, "cannot modify delegate pointer in `@safe` code `%s`", exp)) + { + return ErrorExp.get(); + } + return visit(exp); + } + + Expression visitDelegateFuncptr(DelegateFuncptrExp exp) + { + if (sc.setUnsafe(false, exp.loc, "cannot modify delegate function pointer in `@safe` code `%s`", exp)) + { + return ErrorExp.get(); + } + return visit(exp); + } + + Expression visitIndex(IndexExp exp) + { + //printf("IndexExp::modifiableLvalue(%s)\n", exp.toChars()); + Expression ex = exp.markSettingAAElem(); + if (ex.op == EXP.error) + return ex; + + return visit(exp); + } + + Expression visitCond(CondExp exp) + { + if (!exp.e1.isLvalue() && !exp.e2.isLvalue()) + { + error(exp.loc, "conditional expression `%s` is not a modifiable lvalue", exp.toChars()); + return ErrorExp.get(); + } + exp.e1 = exp.e1.modifiableLvalue(sc, exp.e1); + exp.e2 = exp.e2.modifiableLvalue(sc, exp.e2); + return exp.toLvalue(sc, exp); + } + + switch(_this.op) + { + default: return visit(_this); + case EXP.string_: return visitString(_this.isStringExp()); + case EXP.variable: return visitVar(_this.isVarExp()); + case EXP.star: return visitPtr(_this.isPtrExp()); + case EXP.slice: return visitSlice(_this.isSliceExp()); + case EXP.comma: return visitComma(_this.isCommaExp()); + case EXP.delegatePointer: return visitDelegatePtr(_this.isDelegatePtrExp()); + case EXP.delegateFunctionPointer: return visitDelegateFuncptr(_this.isDelegateFuncptrExp()); + case EXP.index: return visitIndex(_this.isIndexExp()); + case EXP.question: return visitCond(_this.isCondExp()); + } +} + + /**************************************************** * Determine if `exp`, which gets its address taken, can do so safely. * Params: diff --git a/dmd/frontend.h b/dmd/frontend.h index 484ae1e3e0b..e6367a94251 100644 --- a/dmd/frontend.h +++ b/dmd/frontend.h @@ -967,7 +967,6 @@ class Expression : public ASTNode virtual complex_t toComplex(); virtual StringExp* toStringExp(); virtual bool isLvalue(); - virtual Expression* modifiableLvalue(Scope* sc, Expression* e); virtual Expression* resolveLoc(const Loc& loc, Scope* sc); virtual bool checkType(); virtual bool checkValue(); @@ -7161,7 +7160,6 @@ class StringExp final : public Expression int32_t compare(const StringExp* const se2) const; Optional toBool() override; bool isLvalue() override; - Expression* modifiableLvalue(Scope* sc, Expression* e) override; void accept(Visitor* v) override; }; @@ -7316,7 +7314,6 @@ class VarExp final : public SymbolExp static VarExp* create(const Loc& loc, Declaration* var, bool hasOverloads = true); bool equals(const RootObject* const o) const override; bool isLvalue() override; - Expression* modifiableLvalue(Scope* sc, Expression* e) override; void accept(Visitor* v) override; }; @@ -7413,7 +7410,6 @@ class BinAssignExp : public BinExp { public: bool isLvalue() final override; - Expression* modifiableLvalue(Scope* sc, Expression* e) final override; void accept(Visitor* v) override; }; @@ -7473,7 +7469,6 @@ class DotVarExp final : public UnaExp Declaration* var; bool hasOverloads; bool isLvalue() override; - Expression* modifiableLvalue(Scope* sc, Expression* e) override; void accept(Visitor* v) override; }; @@ -7533,7 +7528,6 @@ class PtrExp final : public UnaExp { public: bool isLvalue() override; - Expression* modifiableLvalue(Scope* sc, Expression* e) override; void accept(Visitor* v) override; }; @@ -7613,7 +7607,6 @@ class SliceExp final : public UnaExp public: SliceExp* syntaxCopy() override; bool isLvalue() override; - Expression* modifiableLvalue(Scope* sc, Expression* e) override; Optional toBool() override; void accept(Visitor* v) override; }; @@ -7647,7 +7640,6 @@ class CommaExp final : public BinExp const bool isGenerated; bool allowCommaExp; bool isLvalue() override; - Expression* modifiableLvalue(Scope* sc, Expression* e) override; Optional toBool() override; void accept(Visitor* v) override; static void allow(Expression* exp); @@ -7666,7 +7658,6 @@ class DelegatePtrExp final : public UnaExp { public: bool isLvalue() override; - Expression* modifiableLvalue(Scope* sc, Expression* e) override; void accept(Visitor* v) override; }; @@ -7674,7 +7665,6 @@ class DelegateFuncptrExp final : public UnaExp { public: bool isLvalue() override; - Expression* modifiableLvalue(Scope* sc, Expression* e) override; void accept(Visitor* v) override; }; @@ -7686,7 +7676,6 @@ class IndexExp final : public BinExp bool indexIsInBounds; IndexExp* syntaxCopy() override; bool isLvalue() override; - Expression* modifiableLvalue(Scope* sc, Expression* e) override; void accept(Visitor* v) override; }; @@ -7943,7 +7932,6 @@ class CondExp final : public BinExp Expression* econd; CondExp* syntaxCopy() override; bool isLvalue() override; - Expression* modifiableLvalue(Scope* sc, Expression* e) override; void accept(Visitor* v) override; }; @@ -8011,6 +7999,8 @@ extern Expression* expressionSemantic(Expression* e, Scope* sc); extern Expression* toLvalue(Expression* _this, Scope* sc, Expression* e); +extern Expression* modifiableLvalue(Expression* _this, Scope* sc, Expression* e); + extern const char* toChars(const Initializer* const i); extern void json_generate(Array& modules, OutBuffer& buf); From fe5266be80539c22d08b2ca59899088d2cbeada7 Mon Sep 17 00:00:00 2001 From: Razvan Nitu Date: Tue, 7 Nov 2023 10:56:57 +0200 Subject: [PATCH 008/215] Move expression.resolveLoc to expressionsem (dlang/dmd!15782) --- dmd/expression.d | 86 ------------------------------------- dmd/expression.h | 8 +--- dmd/expressionsem.d | 100 ++++++++++++++++++++++++++++++++++++++++++++ dmd/frontend.h | 8 ---- 4 files changed, 101 insertions(+), 101 deletions(-) diff --git a/dmd/expression.d b/dmd/expression.d index 37ee9ea66cd..baccaa8b076 100644 --- a/dmd/expression.d +++ b/dmd/expression.d @@ -678,15 +678,6 @@ extern (C++) abstract class Expression : ASTNode return false; } - /**************************************** - * Resolve __FILE__, __LINE__, __MODULE__, __FUNCTION__, __PRETTY_FUNCTION__, __FILE_FULL_PATH__ to loc. - */ - Expression resolveLoc(const ref Loc loc, Scope* sc) - { - this.loc = loc; - return this; - } - /**************************************** * Check that the expression has a valid type. * If not, generates an error "... has no type". @@ -3242,12 +3233,6 @@ extern (C++) abstract class UnaExp : Expression } - override final Expression resolveLoc(const ref Loc loc, Scope* sc) - { - e1 = e1.resolveLoc(loc, sc); - return this; - } - override void accept(Visitor v) { v.visit(this); @@ -4954,13 +4939,6 @@ extern (C++) final class CatExp : BinExp super(loc, EXP.concatenate, e1, e2); } - override Expression resolveLoc(const ref Loc loc, Scope* sc) - { - e1 = e1.resolveLoc(loc, sc); - e2 = e2.resolveLoc(loc, sc); - return this; - } - override void accept(Visitor v) { v.visit(this); @@ -5344,19 +5322,6 @@ extern (C++) final class FileInitExp : DefaultInitExp super(loc, tok); } - override Expression resolveLoc(const ref Loc loc, Scope* sc) - { - //printf("FileInitExp::resolve() %s\n", toChars()); - const(char)* s; - if (op == EXP.fileFullPath) - s = FileName.toAbsolute(loc.isValid() ? loc.filename : sc._module.srcfile.toChars()); - else - s = loc.isValid() ? loc.filename : sc._module.ident.toChars(); - - Expression e = new StringExp(loc, s.toDString()); - return e.expressionSemantic(sc); - } - override void accept(Visitor v) { v.visit(this); @@ -5373,12 +5338,6 @@ extern (C++) final class LineInitExp : DefaultInitExp super(loc, EXP.line); } - override Expression resolveLoc(const ref Loc loc, Scope* sc) - { - Expression e = new IntegerExp(loc, loc.linnum, Type.tint32); - return e.expressionSemantic(sc); - } - override void accept(Visitor v) { v.visit(this); @@ -5395,13 +5354,6 @@ extern (C++) final class ModuleInitExp : DefaultInitExp super(loc, EXP.moduleString); } - override Expression resolveLoc(const ref Loc loc, Scope* sc) - { - const auto s = (sc.callsc ? sc.callsc : sc)._module.toPrettyChars().toDString(); - Expression e = new StringExp(loc, s); - return e.expressionSemantic(sc); - } - override void accept(Visitor v) { v.visit(this); @@ -5418,19 +5370,6 @@ extern (C++) final class FuncInitExp : DefaultInitExp super(loc, EXP.functionString); } - override Expression resolveLoc(const ref Loc loc, Scope* sc) - { - const(char)* s; - if (sc.callsc && sc.callsc.func) - s = sc.callsc.func.Dsymbol.toPrettyChars(); - else if (sc.func) - s = sc.func.Dsymbol.toPrettyChars(); - else - s = ""; - Expression e = new StringExp(loc, s.toDString()); - return e.expressionSemantic(sc); - } - override void accept(Visitor v) { v.visit(this); @@ -5447,31 +5386,6 @@ extern (C++) final class PrettyFuncInitExp : DefaultInitExp super(loc, EXP.prettyFunction); } - override Expression resolveLoc(const ref Loc loc, Scope* sc) - { - FuncDeclaration fd = (sc.callsc && sc.callsc.func) - ? sc.callsc.func - : sc.func; - - const(char)* s; - if (fd) - { - const funcStr = fd.Dsymbol.toPrettyChars(); - OutBuffer buf; - functionToBufferWithIdent(fd.type.isTypeFunction(), buf, funcStr, fd.isStatic); - s = buf.extractChars(); - } - else - { - s = ""; - } - - Expression e = new StringExp(loc, s.toDString()); - e = e.expressionSemantic(sc); - e.type = Type.tstring; - return e; - } - override void accept(Visitor v) { v.visit(this); diff --git a/dmd/expression.h b/dmd/expression.h index ca3d021c9ec..beb913c8895 100644 --- a/dmd/expression.h +++ b/dmd/expression.h @@ -50,6 +50,7 @@ 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 *e); Expression *modifiableLvalue(Expression* exp, Scope *sc, Expression *e); @@ -101,7 +102,6 @@ class Expression : public ASTNode virtual complex_t toComplex(); virtual StringExp *toStringExp(); virtual bool isLvalue(); - virtual Expression *resolveLoc(const Loc &loc, Scope *sc); virtual bool checkType(); virtual bool checkValue(); Expression *addressOf(); @@ -666,7 +666,6 @@ class UnaExp : public Expression Expression *e1; UnaExp *syntaxCopy() override; - Expression *resolveLoc(const Loc &loc, Scope *sc) override final; void accept(Visitor *v) override { v->visit(this); } }; @@ -1285,35 +1284,30 @@ class DefaultInitExp : public Expression 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); } }; diff --git a/dmd/expressionsem.d b/dmd/expressionsem.d index 3d2b3b01f19..76d8dba5bab 100644 --- a/dmd/expressionsem.d +++ b/dmd/expressionsem.d @@ -14871,6 +14871,106 @@ bool checkSharedAccess(Expression e, Scope* sc, bool returnRef = false) return check(e, returnRef); } +/**************************************** + * Resolve __FILE__, __LINE__, __MODULE__, __FUNCTION__, __PRETTY_FUNCTION__, __FILE_FULL_PATH__ to loc. + */ +Expression resolveLoc(Expression exp, const ref Loc loc, Scope* sc) +{ + Expression visit(Expression exp) + { + if (auto unaExp = exp.isUnaExp()) + { + unaExp.e1 = unaExp.e1.resolveLoc(loc, sc); + return unaExp; + } + exp.loc = loc; + return exp; + } + + Expression visitCat(CatExp exp) + { + exp.e1 = exp.e1.resolveLoc(loc, sc); + exp.e2 = exp.e2.resolveLoc(loc, sc); + return exp; + } + + Expression visitFileInit(FileInitExp exp) + { + //printf("FileInitExp::resolve() %s\n", exp.toChars()); + const(char)* s; + if (exp.op == EXP.fileFullPath) + s = FileName.toAbsolute(loc.isValid() ? loc.filename : sc._module.srcfile.toChars()); + else + s = loc.isValid() ? loc.filename : sc._module.ident.toChars(); + + Expression e = new StringExp(loc, s.toDString()); + return e.expressionSemantic(sc); + } + + Expression visitLineInit(LineInitExp _) + { + Expression e = new IntegerExp(loc, loc.linnum, Type.tint32); + return e.expressionSemantic(sc); + } + + Expression visitModuleInit(ModuleInitExp _) + { + const auto s = (sc.callsc ? sc.callsc : sc)._module.toPrettyChars().toDString(); + Expression e = new StringExp(loc, s); + return e.expressionSemantic(sc); + } + + Expression visitFuncInit(FuncInitExp _) + { + const(char)* s; + if (sc.callsc && sc.callsc.func) + s = sc.callsc.func.Dsymbol.toPrettyChars(); + else if (sc.func) + s = sc.func.Dsymbol.toPrettyChars(); + else + s = ""; + Expression e = new StringExp(loc, s.toDString()); + return e.expressionSemantic(sc); + } + + Expression visitPrettyFunc(PrettyFuncInitExp _) + { + FuncDeclaration fd = (sc.callsc && sc.callsc.func) + ? sc.callsc.func + : sc.func; + + const(char)* s; + if (fd) + { + const funcStr = fd.Dsymbol.toPrettyChars(); + OutBuffer buf; + functionToBufferWithIdent(fd.type.isTypeFunction(), buf, funcStr, fd.isStatic); + s = buf.extractChars(); + } + else + { + s = ""; + } + + Expression e = new StringExp(loc, s.toDString()); + e = e.expressionSemantic(sc); + e.type = Type.tstring; + return e; + } + + switch(exp.op) + { + default: return visit(exp); + case EXP.concatenate: return visitCat(exp.isCatExp()); + case EXP.file: + case EXP.fileFullPath: return visitFileInit(exp.isFileInitExp()); + case EXP.line: return visitLineInit(exp.isLineInitExp); + case EXP.moduleString: return visitModuleInit(exp.isModuleInitExp()); + case EXP.functionString: return visitFuncInit(exp.isFuncInitExp()); + case EXP.prettyFunction: return visitPrettyFunc(exp.isPrettyFuncInitExp()); + } +} + /************************************************ * Destructors are attached to VarDeclarations. * Hence, if expression returns a temp that needs a destructor, diff --git a/dmd/frontend.h b/dmd/frontend.h index e6367a94251..d6c42d7b928 100644 --- a/dmd/frontend.h +++ b/dmd/frontend.h @@ -967,7 +967,6 @@ class Expression : public ASTNode virtual complex_t toComplex(); virtual StringExp* toStringExp(); virtual bool isLvalue(); - virtual Expression* resolveLoc(const Loc& loc, Scope* sc); virtual bool checkType(); virtual bool checkValue(); Expression* addressOf(); @@ -7390,7 +7389,6 @@ class UnaExp : public Expression Expression* e1; UnaExp* syntaxCopy() override; void setNoderefOperand(); - Expression* resolveLoc(const Loc& loc, Scope* sc) final override; void accept(Visitor* v) override; }; @@ -7826,7 +7824,6 @@ class CatExp final : public BinExp { public: Expression* lowering; - Expression* resolveLoc(const Loc& loc, Scope* sc) override; void accept(Visitor* v) override; }; @@ -7944,35 +7941,30 @@ class DefaultInitExp : public Expression class FileInitExp final : public DefaultInitExp { public: - Expression* resolveLoc(const Loc& loc, Scope* sc) override; void accept(Visitor* v) override; }; class LineInitExp final : public DefaultInitExp { public: - Expression* resolveLoc(const Loc& loc, Scope* sc) override; void accept(Visitor* v) override; }; class ModuleInitExp final : public DefaultInitExp { public: - Expression* resolveLoc(const Loc& loc, Scope* sc) override; void accept(Visitor* v) override; }; class FuncInitExp final : public DefaultInitExp { public: - Expression* resolveLoc(const Loc& loc, Scope* sc) override; void accept(Visitor* v) override; }; class PrettyFuncInitExp final : public DefaultInitExp { public: - Expression* resolveLoc(const Loc& loc, Scope* sc) override; void accept(Visitor* v) override; }; From 07deb0ee2ee56d73db63f77114d345723fa3f952 Mon Sep 17 00:00:00 2001 From: RazvanN7 Date: Tue, 7 Nov 2023 13:32:18 +0200 Subject: [PATCH 009/215] Break expression.d dependency on scope.d and expressionsem.d --- dmd/expression.d | 130 ------------------------------------------ dmd/expressionsem.d | 135 +++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 133 insertions(+), 132 deletions(-) diff --git a/dmd/expression.d b/dmd/expression.d index baccaa8b076..b7825e682d6 100644 --- a/dmd/expression.d +++ b/dmd/expression.d @@ -30,13 +30,11 @@ import dmd.dclass; import dmd.declaration; import dmd.dimport; import dmd.dmodule; -import dmd.dscope; import dmd.dstruct; import dmd.dsymbol; import dmd.dtemplate; import dmd.errors; import dmd.errorsink; -import dmd.expressionsem; import dmd.func; import dmd.globals; import dmd.hdrgen; @@ -118,45 +116,6 @@ inout(Expression) lastComma(inout Expression e) } -/*********************************** - * Determine if a `this` is needed to access `d`. - * Params: - * sc = context - * d = declaration to check - * Returns: - * true means a `this` is needed - */ -bool isNeedThisScope(Scope* sc, Declaration d) -{ - if (sc.intypeof == 1) - return false; - - AggregateDeclaration ad = d.isThis(); - if (!ad) - return false; - //printf("d = %s, ad = %s\n", d.toChars(), ad.toChars()); - - for (Dsymbol s = sc.parent; s; s = s.toParentLocal()) - { - //printf("\ts = %s %s, toParent2() = %p\n", s.kind(), s.toChars(), s.toParent2()); - if (AggregateDeclaration ad2 = s.isAggregateDeclaration()) - { - if (ad2 == ad) - return false; - else if (ad2.isNested()) - continue; - else - return true; - } - if (FuncDeclaration f = s.isFuncDeclaration()) - { - if (f.isMemberLocal()) - break; - } - } - return true; -} - /**************************************** * Expand tuples in-place. * @@ -2940,52 +2899,6 @@ extern (C++) final class FuncExp : Expression return false; } - extern (D) void genIdent(Scope* sc) - { - if (fd.ident == Id.empty) - { - const(char)[] s; - if (fd.fes) - s = "__foreachbody"; - else if (fd.tok == TOK.reserved) - s = "__lambda"; - else if (fd.tok == TOK.delegate_) - s = "__dgliteral"; - else - s = "__funcliteral"; - - DsymbolTable symtab; - if (FuncDeclaration func = sc.parent.isFuncDeclaration()) - { - if (func.localsymtab is null) - { - // Inside template constraint, symtab is not set yet. - // Initialize it lazily. - func.localsymtab = new DsymbolTable(); - } - symtab = func.localsymtab; - } - else - { - ScopeDsymbol sds = sc.parent.isScopeDsymbol(); - if (!sds.symtab) - { - // Inside template constraint, symtab may not be set yet. - // Initialize it lazily. - assert(sds.isTemplateInstance()); - sds.symtab = new DsymbolTable(); - } - symtab = sds.symtab; - } - assert(symtab); - Identifier id = Identifier.generateId(s, symtab.length() + 1); - fd.ident = id; - if (td) - td.ident = id; - symtab.insert(td ? cast(Dsymbol)td : cast(Dsymbol)fd); - } - } - override FuncExp syntaxCopy() { if (td) @@ -3587,49 +3500,6 @@ extern (C++) final class DotTemplateInstanceExp : UnaExp return new DotTemplateInstanceExp(loc, e1.syntaxCopy(), ti.name, TemplateInstance.arraySyntaxCopy(ti.tiargs)); } - extern (D) bool findTempDecl(Scope* sc) - { - static if (LOGSEMANTIC) - { - printf("DotTemplateInstanceExp::findTempDecl('%s')\n", toChars()); - } - if (ti.tempdecl) - return true; - - Expression e = new DotIdExp(loc, e1, ti.name); - e = e.expressionSemantic(sc); - if (e.op == EXP.dot) - e = (cast(DotExp)e).e2; - - Dsymbol s = null; - switch (e.op) - { - case EXP.overloadSet: - s = (cast(OverExp)e).vars; - break; - - case EXP.dotTemplateDeclaration: - s = (cast(DotTemplateExp)e).td; - break; - - case EXP.scope_: - s = (cast(ScopeExp)e).sds; - break; - - case EXP.dotVariable: - s = (cast(DotVarExp)e).var; - break; - - case EXP.variable: - s = (cast(VarExp)e).var; - break; - - default: - return false; - } - return ti.updateTempDecl(sc, s); - } - override bool checkType() { // Same logic as ScopeExp.checkType() diff --git a/dmd/expressionsem.d b/dmd/expressionsem.d index 76d8dba5bab..b3d753600c4 100644 --- a/dmd/expressionsem.d +++ b/dmd/expressionsem.d @@ -87,6 +87,46 @@ import dmd.visitor; enum LOGSEMANTIC = false; +/*********************************** + * Determine if a `this` is needed to access `d`. + * Params: + * sc = context + * d = declaration to check + * Returns: + * true means a `this` is needed + */ +private bool isNeedThisScope(Scope* sc, Declaration d) +{ + if (sc.intypeof == 1) + return false; + + AggregateDeclaration ad = d.isThis(); + if (!ad) + return false; + //printf("d = %s, ad = %s\n", d.toChars(), ad.toChars()); + + for (Dsymbol s = sc.parent; s; s = s.toParentLocal()) + { + //printf("\ts = %s %s, toParent2() = %p\n", s.kind(), s.toChars(), s.toParent2()); + if (AggregateDeclaration ad2 = s.isAggregateDeclaration()) + { + if (ad2 == ad) + return false; + else if (ad2.isNested()) + continue; + else + return true; + } + if (FuncDeclaration f = s.isFuncDeclaration()) + { + if (f.isMemberLocal()) + break; + } + } + return true; +} + + /******************************************************** * Perform semantic analysis and CTFE on expressions to produce * a string. @@ -196,6 +236,51 @@ FuncDeclaration hasThis(Scope* sc) } +extern (D) bool findTempDecl(DotTemplateInstanceExp exp, Scope* sc) +{ + auto ti = exp.ti; + auto e1 = exp.e1; + static if (LOGSEMANTIC) + { + printf("DotTemplateInstanceExp::findTempDecl('%s')\n", exp.toChars()); + } + if (ti.tempdecl) + return true; + + Expression e = new DotIdExp(exp.loc, e1, ti.name); + e = e.expressionSemantic(sc); + if (e.op == EXP.dot) + e = (cast(DotExp)e).e2; + + Dsymbol s = null; + switch (e.op) + { + case EXP.overloadSet: + s = (cast(OverExp)e).vars; + break; + + case EXP.dotTemplateDeclaration: + s = (cast(DotTemplateExp)e).td; + break; + + case EXP.scope_: + s = (cast(ScopeExp)e).sds; + break; + + case EXP.dotVariable: + s = (cast(DotVarExp)e).var; + break; + + case EXP.variable: + s = (cast(VarExp)e).var; + break; + + default: + return false; + } + return ti.updateTempDecl(sc, s); +} + /*********************************************************** * Resolve `exp` as a compile-time known string. * Params: @@ -5249,6 +5334,52 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor result = e; } + private void genIdent(FuncExp exp, Scope* sc) + { + if (exp.fd.ident == Id.empty) + { + const(char)[] s; + if (exp.fd.fes) + s = "__foreachbody"; + else if (exp.fd.tok == TOK.reserved) + s = "__lambda"; + else if (exp.fd.tok == TOK.delegate_) + s = "__dgliteral"; + else + s = "__funcliteral"; + + DsymbolTable symtab; + if (FuncDeclaration func = sc.parent.isFuncDeclaration()) + { + if (func.localsymtab is null) + { + // Inside template constraint, symtab is not set yet. + // Initialize it lazily. + func.localsymtab = new DsymbolTable(); + } + symtab = func.localsymtab; + } + else + { + ScopeDsymbol sds = sc.parent.isScopeDsymbol(); + if (!sds.symtab) + { + // Inside template constraint, symtab may not be set yet. + // Initialize it lazily. + assert(sds.isTemplateInstance()); + sds.symtab = new DsymbolTable(); + } + symtab = sds.symtab; + } + assert(symtab); + Identifier id = Identifier.generateId(s, symtab.length() + 1); + exp.fd.ident = id; + if (exp.td) + exp.td.ident = id; + symtab.insert(exp.td ? cast(Dsymbol)exp.td : cast(Dsymbol)exp.fd); + } + } + override void visit(FuncExp exp) { static if (LOGSEMANTIC) @@ -5279,7 +5410,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor //if (fd.treq) // fd.treq = fd.treq.dsymbolSemantic(loc, sc); - exp.genIdent(sc); + genIdent(exp, sc); // Set target of return type inference if (exp.fd.treq && !exp.fd.type.nextOf()) @@ -5392,7 +5523,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor return checkarg; } - exp.genIdent(sc); + genIdent(exp, sc); assert(exp.td.parameters && exp.td.parameters.length); exp.td.dsymbolSemantic(sc); From a3c49b251446dc2549e10c942f910745cec4dcc8 Mon Sep 17 00:00:00 2001 From: RazvanN7 Date: Tue, 7 Nov 2023 11:50:56 +0200 Subject: [PATCH 010/215] Break dependency of expression.d on ctfeexp.d --- dmd/compiler.d | 1 + dmd/ctfeexpr.d | 227 +++---- dmd/expression.d | 237 +++++--- dmd/frontend.h | 959 +++++++++++++++--------------- tests/dmd/unit/deinitialization.d | 3 +- 5 files changed, 710 insertions(+), 717 deletions(-) diff --git a/dmd/compiler.d b/dmd/compiler.d index 7950581e788..7ace90178b2 100644 --- a/dmd/compiler.d +++ b/dmd/compiler.d @@ -15,6 +15,7 @@ import core.stdc.string; import dmd.astenums; import dmd.arraytypes; +import dmd.ctfeexpr; import dmd.dmodule; import dmd.errors; import dmd.expression; diff --git a/dmd/ctfeexpr.d b/dmd/ctfeexpr.d index ddfb57d22d7..c93269fb321 100644 --- a/dmd/ctfeexpr.d +++ b/dmd/ctfeexpr.d @@ -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) - { - 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; - } +private: + // Ensure that the union is suitably aligned. + align(8) union _AnonStruct_u + { + 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; + } + + _AnonStruct_u u; +} - override void accept(Visitor v) - { - v.visit(this); - } +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 ""; - case EXP.voidExpression: - return "cast(void)0"; - case EXP.showCtfeContext: - return ""; - case EXP.break_: - return ""; - case EXP.continue_: - return ""; - case EXP.goto_: - return ""; - 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 { diff --git a/dmd/expression.d b/dmd/expression.d index b7825e682d6..e98a8ee0c30 100644 --- a/dmd/expression.d +++ b/dmd/expression.d @@ -18,14 +18,10 @@ import core.stdc.stdio; import core.stdc.string; import dmd.aggregate; -import dmd.aliasthis; -import dmd.arrayop; import dmd.arraytypes; import dmd.astenums; import dmd.ast_node; import dmd.gluelayer; -import dmd.ctfeexpr; -import dmd.ctorflow; import dmd.dclass; import dmd.declaration; import dmd.dimport; @@ -43,39 +39,21 @@ import dmd.identifier; import dmd.init; import dmd.location; import dmd.mtype; -import dmd.opover; import dmd.optimize; import dmd.root.complex; import dmd.root.ctfloat; -import dmd.root.filename; import dmd.common.outbuffer; import dmd.root.optional; import dmd.root.rmem; import dmd.rootobject; import dmd.root.string; import dmd.root.utf; -import dmd.safe; import dmd.target; import dmd.tokens; import dmd.visitor; enum LOGSEMANTIC = false; -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); -} - /// Return value for `checkModifiable` enum Modifiable { @@ -274,70 +252,6 @@ TemplateDeclaration getFuncTemplateDecl(Dsymbol s) @safe return null; } -/****************************************************************/ -/* 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 (D) struct UnionExp -{ - // yes, default constructor does nothing - extern (D) this(Expression e) - { - memcpy(&this, cast(void*)e, e.size); - } - - /* Extract pointer to Expression - */ - extern (D) Expression exp() return - { - return cast(Expression)&u; - } - - /* Convert to an allocated Expression - */ - extern (D) Expression copy() - { - Expression e = exp(); - //if (e.size > sizeof(u)) printf("%s\n", EXPtoString(e.op).ptr); - assert(e.size <= u.sizeof); - switch (e.op) - { - 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(); - } - } - -private: - // Ensure that the union is suitably aligned. - align(8) union _AnonStruct_u - { - 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; - } - - _AnonStruct_u u; -} - /************************ TypeDotIdExp ************************************/ /* Things like: * int.size @@ -1195,7 +1109,7 @@ extern (C++) final class IntegerExp : Expression */ extern (C++) final class ErrorExp : Expression { - private extern (D) this() + extern (D) this() { super(Loc.initial, EXP.error); type = Type.terror; @@ -5262,6 +5176,155 @@ extern (C++) final class PrettyFuncInitExp : DefaultInitExp } } +/*********************************************************** + * 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). + */ +extern (C++) final class ClassReferenceExp : Expression +{ + StructLiteralExp value; + + extern (D) this(const ref Loc loc, StructLiteralExp lit, Type type) @safe + { + super(loc, EXP.classReference); + assert(lit && lit.sd && lit.sd.isClassDeclaration()); + this.value = lit; + this.type = type; + } + + ClassDeclaration originalClass() + { + return value.sd.isClassDeclaration(); + } + + // Return index of the field, or -1 if not found + int getFieldIndex(Type fieldtype, uint fieldoffset) + { + ClassDeclaration cd = originalClass(); + uint 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 (fieldoffset == v2.offset && fieldtype.size() == v2.type.size()) + { + return cast(int)(value.elements.length - fieldsSoFar - cd.fields.length + (j - fieldsSoFar)); + } + } + 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) + { + 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; + } + + 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 ""; + case EXP.voidExpression: + return "cast(void)0"; + case EXP.showCtfeContext: + return ""; + case EXP.break_: + return ""; + case EXP.continue_: + return ""; + case EXP.goto_: + return ""; + 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_; + } +} + +/*********************************************************** + * 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"; + } + + override void accept(Visitor v) + { + v.visit(this); + } +} + /** * Objective-C class reference expression. * diff --git a/dmd/frontend.h b/dmd/frontend.h index d6c42d7b928..0095cb087f4 100644 --- a/dmd/frontend.h +++ b/dmd/frontend.h @@ -117,6 +117,56 @@ class StaticIfCondition; class ForeachStatement; class ForeachRangeStatement; struct OutBuffer; +class TypeInfoClassDeclaration; +class Initializer; +struct IntRange; +struct ModuleDeclaration; +template +struct FileMapping; +struct Escape; +class ErrorSink; +class LabelStatement; +class SwitchStatement; +class Statement; +class TryFinallyStatement; +class ScopeGuardStatement; +struct DocComment; +class WithStatement; +struct AA; +class Tuple; +class Parameter; +class TemplateParameter; +struct TemplatePrevious; +struct TYPE; +class TypeBasic; +class TypeFunction; +class TypeError; +class TypeVector; +class TypeSArray; +class TypeDArray; +class TypeAArray; +class TypePointer; +class TypeReference; +class TypeDelegate; +class TypeIdentifier; +class TypeInstance; +class TypeTypeof; +class TypeReturn; +class TypeStruct; +class TypeEnum; +class TypeClass; +class TypeSlice; +class TypeNull; +class TypeMixin; +class TypeTraits; +class TypeNoreturn; +class TypeTag; +class TemplateTypeParameter; +class TemplateValueParameter; +class TemplateAliasParameter; +class TemplateThisParameter; +class TemplateTupleParameter; +class TypeQualified; class StringExp; class IntegerExp; class ErrorExp; @@ -231,56 +281,6 @@ class ThrownExceptionExp; class UnaExp; class BinExp; class BinAssignExp; -class TypeInfoClassDeclaration; -class Initializer; -struct IntRange; -struct ModuleDeclaration; -template -struct FileMapping; -struct Escape; -class ErrorSink; -class LabelStatement; -class SwitchStatement; -class Statement; -class TryFinallyStatement; -class ScopeGuardStatement; -struct DocComment; -class WithStatement; -struct AA; -class Tuple; -class Parameter; -class TemplateParameter; -struct TemplatePrevious; -struct TYPE; -class TypeBasic; -class TypeFunction; -class TypeError; -class TypeVector; -class TypeSArray; -class TypeDArray; -class TypeAArray; -class TypePointer; -class TypeReference; -class TypeDelegate; -class TypeIdentifier; -class TypeInstance; -class TypeTypeof; -class TypeReturn; -class TypeStruct; -class TypeEnum; -class TypeClass; -class TypeSlice; -class TypeNull; -class TypeMixin; -class TypeTraits; -class TypeNoreturn; -class TypeTag; -class TemplateTypeParameter; -class TemplateValueParameter; -class TemplateAliasParameter; -class TemplateThisParameter; -class TemplateTupleParameter; -class TypeQualified; class CaseStatement; class Catch; struct Designator; @@ -745,352 +745,48 @@ enum class BUILTIN : uint8_t yl2x = 31u, yl2xp1 = 32u, toPrecFloat = 33u, - toPrecDouble = 34u, - toPrecReal = 35u, -}; - -enum class Include : uint8_t -{ - notComputed = 0u, - yes = 1u, - no = 2u, -}; - -struct FileName final -{ -private: - _d_dynamicArray< const char > str; -public: - static FileName create(const char* name); - static bool equals(const char* name1, const char* name2); - static bool absolute(const char* name); - static const char* toAbsolute(const char* name, const char* base = nullptr); - static const char* ext(const char* str); - const char* ext() const; - static const char* removeExt(const char* str); - static const char* name(const char* str); - const char* name() const; - static const char* path(const char* str); - static const char* combine(const char* path, const char* name); - static Array* splitPath(const char* path); - static const char* defaultExt(const char* name, const char* ext); - static const char* forceExt(const char* name, const char* ext); - static bool equalsExt(const char* name, const char* ext); - bool equalsExt(const char* ext) const; - static const char* searchPath(Array* path, const char* name, bool cwd); - static int32_t exists(const char* name); - static bool ensurePathExists(const char* path); - static const char* canonicalName(const char* name); - static void free(const char* str); - const char* toChars() const; - FileName() : - str() - { - } -}; - -enum class EXP : uint8_t -{ - reserved = 0u, - negate = 1u, - cast_ = 2u, - null_ = 3u, - assert_ = 4u, - array = 5u, - call = 6u, - address = 7u, - type = 8u, - throw_ = 9u, - new_ = 10u, - delete_ = 11u, - star = 12u, - symbolOffset = 13u, - variable = 14u, - dotVariable = 15u, - dotIdentifier = 16u, - dotTemplateInstance = 17u, - dotType = 18u, - slice = 19u, - arrayLength = 20u, - dollar = 21u, - template_ = 22u, - dotTemplateDeclaration = 23u, - declaration = 24u, - dSymbol = 25u, - typeid_ = 26u, - uadd = 27u, - remove = 28u, - newAnonymousClass = 29u, - arrayLiteral = 30u, - assocArrayLiteral = 31u, - structLiteral = 32u, - classReference = 33u, - thrownException = 34u, - delegatePointer = 35u, - delegateFunctionPointer = 36u, - lessThan = 37u, - greaterThan = 38u, - lessOrEqual = 39u, - greaterOrEqual = 40u, - equal = 41u, - notEqual = 42u, - identity = 43u, - notIdentity = 44u, - index = 45u, - is_ = 46u, - leftShift = 47u, - rightShift = 48u, - leftShiftAssign = 49u, - rightShiftAssign = 50u, - unsignedRightShift = 51u, - unsignedRightShiftAssign = 52u, - concatenate = 53u, - concatenateAssign = 54u, - concatenateElemAssign = 55u, - concatenateDcharAssign = 56u, - add = 57u, - min = 58u, - addAssign = 59u, - minAssign = 60u, - mul = 61u, - div = 62u, - mod = 63u, - mulAssign = 64u, - divAssign = 65u, - modAssign = 66u, - and_ = 67u, - or_ = 68u, - xor_ = 69u, - andAssign = 70u, - orAssign = 71u, - xorAssign = 72u, - assign = 73u, - not_ = 74u, - tilde = 75u, - plusPlus = 76u, - minusMinus = 77u, - construct = 78u, - blit = 79u, - dot = 80u, - comma = 81u, - question = 82u, - andAnd = 83u, - orOr = 84u, - prePlusPlus = 85u, - preMinusMinus = 86u, - identifier = 87u, - string_ = 88u, - this_ = 89u, - super_ = 90u, - halt = 91u, - tuple = 92u, - error = 93u, - void_ = 94u, - int64 = 95u, - float64 = 96u, - complex80 = 97u, - import_ = 98u, - delegate_ = 99u, - function_ = 100u, - mixin_ = 101u, - in_ = 102u, - break_ = 103u, - continue_ = 104u, - goto_ = 105u, - scope_ = 106u, - traits = 107u, - overloadSet = 108u, - line = 109u, - file = 110u, - fileFullPath = 111u, - moduleString = 112u, - functionString = 113u, - prettyFunction = 114u, - pow = 115u, - powAssign = 116u, - vector = 117u, - voidExpression = 118u, - cantExpression = 119u, - showCtfeContext = 120u, - objcClassReference = 121u, - vectorArray = 122u, - compoundLiteral = 123u, - _Generic_ = 124u, - interval = 125u, - loweredAssignExp = 126u, -}; - -typedef uint64_t dinteger_t; - -struct complex_t final -{ - _d_real re; - _d_real im; - complex_t() = delete; - complex_t(_d_real re); - complex_t(_d_real re, _d_real im); - int32_t opEquals(complex_t y) const; -}; - -template -struct Optional final -{ - T value; - bool present; - Optional(T value); - static Optional create(T val); - bool isPresent() const; - bool isEmpty() const; - T get(); - bool hasValue(T exp) const; - Optional() - { - } -}; - -class Expression : public ASTNode -{ -public: - Type* type; - Loc loc; - const EXP op; - size_t size() const; - static void _init(); - static void deinitialize(); - virtual Expression* syntaxCopy(); - DYNCAST dyncast() const final override; - const char* toChars() const override; - virtual dinteger_t toInteger(); - virtual uinteger_t toUInteger(); - virtual _d_real toReal(); - virtual _d_real toImaginary(); - virtual complex_t toComplex(); - virtual StringExp* toStringExp(); - virtual bool isLvalue(); - virtual bool checkType(); - virtual bool checkValue(); - Expression* addressOf(); - Expression* deref(); - Expression* optimize(int32_t result, bool keepLvalue = false); - int32_t isConst(); - virtual bool isIdentical(const Expression* const e) const; - virtual Optional toBool(); - virtual bool hasCode(); - IntegerExp* isIntegerExp(); - ErrorExp* isErrorExp(); - VoidInitExp* isVoidInitExp(); - RealExp* isRealExp(); - ComplexExp* isComplexExp(); - IdentifierExp* isIdentifierExp(); - DollarExp* isDollarExp(); - DsymbolExp* isDsymbolExp(); - ThisExp* isThisExp(); - SuperExp* isSuperExp(); - NullExp* isNullExp(); - StringExp* isStringExp(); - TupleExp* isTupleExp(); - ArrayLiteralExp* isArrayLiteralExp(); - AssocArrayLiteralExp* isAssocArrayLiteralExp(); - StructLiteralExp* isStructLiteralExp(); - CompoundLiteralExp* isCompoundLiteralExp(); - TypeExp* isTypeExp(); - ScopeExp* isScopeExp(); - TemplateExp* isTemplateExp(); - NewExp* isNewExp(); - NewAnonClassExp* isNewAnonClassExp(); - SymOffExp* isSymOffExp(); - VarExp* isVarExp(); - OverExp* isOverExp(); - FuncExp* isFuncExp(); - DeclarationExp* isDeclarationExp(); - TypeidExp* isTypeidExp(); - TraitsExp* isTraitsExp(); - HaltExp* isHaltExp(); - IsExp* isExp(); - MixinExp* isMixinExp(); - ImportExp* isImportExp(); - AssertExp* isAssertExp(); - ThrowExp* isThrowExp(); - DotIdExp* isDotIdExp(); - DotTemplateExp* isDotTemplateExp(); - DotVarExp* isDotVarExp(); - DotTemplateInstanceExp* isDotTemplateInstanceExp(); - DelegateExp* isDelegateExp(); - DotTypeExp* isDotTypeExp(); - CallExp* isCallExp(); - AddrExp* isAddrExp(); - PtrExp* isPtrExp(); - NegExp* isNegExp(); - UAddExp* isUAddExp(); - ComExp* isComExp(); - NotExp* isNotExp(); - DeleteExp* isDeleteExp(); - CastExp* isCastExp(); - VectorExp* isVectorExp(); - VectorArrayExp* isVectorArrayExp(); - SliceExp* isSliceExp(); - ArrayLengthExp* isArrayLengthExp(); - ArrayExp* isArrayExp(); - DotExp* isDotExp(); - CommaExp* isCommaExp(); - IntervalExp* isIntervalExp(); - DelegatePtrExp* isDelegatePtrExp(); - DelegateFuncptrExp* isDelegateFuncptrExp(); - IndexExp* isIndexExp(); - PostExp* isPostExp(); - PreExp* isPreExp(); - AssignExp* isAssignExp(); - LoweredAssignExp* isLoweredAssignExp(); - ConstructExp* isConstructExp(); - BlitExp* isBlitExp(); - AddAssignExp* isAddAssignExp(); - MinAssignExp* isMinAssignExp(); - MulAssignExp* isMulAssignExp(); - DivAssignExp* isDivAssignExp(); - ModAssignExp* isModAssignExp(); - AndAssignExp* isAndAssignExp(); - OrAssignExp* isOrAssignExp(); - XorAssignExp* isXorAssignExp(); - PowAssignExp* isPowAssignExp(); - ShlAssignExp* isShlAssignExp(); - ShrAssignExp* isShrAssignExp(); - UshrAssignExp* isUshrAssignExp(); - CatAssignExp* isCatAssignExp(); - CatElemAssignExp* isCatElemAssignExp(); - CatDcharAssignExp* isCatDcharAssignExp(); - AddExp* isAddExp(); - MinExp* isMinExp(); - CatExp* isCatExp(); - MulExp* isMulExp(); - DivExp* isDivExp(); - ModExp* isModExp(); - PowExp* isPowExp(); - ShlExp* isShlExp(); - ShrExp* isShrExp(); - UshrExp* isUshrExp(); - AndExp* isAndExp(); - OrExp* isOrExp(); - XorExp* isXorExp(); - LogicalExp* isLogicalExp(); - InExp* isInExp(); - RemoveExp* isRemoveExp(); - EqualExp* isEqualExp(); - IdentityExp* isIdentityExp(); - CondExp* isCondExp(); - GenericExp* isGenericExp(); - DefaultInitExp* isDefaultInitExp(); - FileInitExp* isFileInitExp(); - LineInitExp* isLineInitExp(); - ModuleInitExp* isModuleInitExp(); - FuncInitExp* isFuncInitExp(); - PrettyFuncInitExp* isPrettyFuncInitExp(); - ObjcClassReferenceExp* isObjcClassReferenceExp(); - ClassReferenceExp* isClassReferenceExp(); - ThrownExceptionExp* isThrownExceptionExp(); - UnaExp* isUnaExp(); - BinExp* isBinExp(); - BinAssignExp* isBinAssignExp(); - void accept(Visitor* v) override; + toPrecDouble = 34u, + toPrecReal = 35u, +}; + +enum class Include : uint8_t +{ + notComputed = 0u, + yes = 1u, + no = 2u, +}; + +struct FileName final +{ +private: + _d_dynamicArray< const char > str; +public: + static FileName create(const char* name); + static bool equals(const char* name1, const char* name2); + static bool absolute(const char* name); + static const char* toAbsolute(const char* name, const char* base = nullptr); + static const char* ext(const char* str); + const char* ext() const; + static const char* removeExt(const char* str); + static const char* name(const char* str); + const char* name() const; + static const char* path(const char* str); + static const char* combine(const char* path, const char* name); + static Array* splitPath(const char* path); + static const char* defaultExt(const char* name, const char* ext); + static const char* forceExt(const char* name, const char* ext); + static bool equalsExt(const char* name, const char* ext); + bool equalsExt(const char* ext) const; + static const char* searchPath(Array* path, const char* name, bool cwd); + static int32_t exists(const char* name); + static bool ensurePathExists(const char* path); + static const char* canonicalName(const char* name); + static void free(const char* str); + const char* toChars() const; + FileName() : + str() + { + } }; enum class MATCH @@ -1328,6 +1024,8 @@ enum class Covariant fwdref = 3, }; +typedef uint64_t dinteger_t; + class Type : public ASTNode { public: @@ -1553,6 +1251,163 @@ class Type : public ASTNode TypeFunction* toTypeFunction(); }; +enum class EXP : uint8_t +{ + reserved = 0u, + negate = 1u, + cast_ = 2u, + null_ = 3u, + assert_ = 4u, + array = 5u, + call = 6u, + address = 7u, + type = 8u, + throw_ = 9u, + new_ = 10u, + delete_ = 11u, + star = 12u, + symbolOffset = 13u, + variable = 14u, + dotVariable = 15u, + dotIdentifier = 16u, + dotTemplateInstance = 17u, + dotType = 18u, + slice = 19u, + arrayLength = 20u, + dollar = 21u, + template_ = 22u, + dotTemplateDeclaration = 23u, + declaration = 24u, + dSymbol = 25u, + typeid_ = 26u, + uadd = 27u, + remove = 28u, + newAnonymousClass = 29u, + arrayLiteral = 30u, + assocArrayLiteral = 31u, + structLiteral = 32u, + classReference = 33u, + thrownException = 34u, + delegatePointer = 35u, + delegateFunctionPointer = 36u, + lessThan = 37u, + greaterThan = 38u, + lessOrEqual = 39u, + greaterOrEqual = 40u, + equal = 41u, + notEqual = 42u, + identity = 43u, + notIdentity = 44u, + index = 45u, + is_ = 46u, + leftShift = 47u, + rightShift = 48u, + leftShiftAssign = 49u, + rightShiftAssign = 50u, + unsignedRightShift = 51u, + unsignedRightShiftAssign = 52u, + concatenate = 53u, + concatenateAssign = 54u, + concatenateElemAssign = 55u, + concatenateDcharAssign = 56u, + add = 57u, + min = 58u, + addAssign = 59u, + minAssign = 60u, + mul = 61u, + div = 62u, + mod = 63u, + mulAssign = 64u, + divAssign = 65u, + modAssign = 66u, + and_ = 67u, + or_ = 68u, + xor_ = 69u, + andAssign = 70u, + orAssign = 71u, + xorAssign = 72u, + assign = 73u, + not_ = 74u, + tilde = 75u, + plusPlus = 76u, + minusMinus = 77u, + construct = 78u, + blit = 79u, + dot = 80u, + comma = 81u, + question = 82u, + andAnd = 83u, + orOr = 84u, + prePlusPlus = 85u, + preMinusMinus = 86u, + identifier = 87u, + string_ = 88u, + this_ = 89u, + super_ = 90u, + halt = 91u, + tuple = 92u, + error = 93u, + void_ = 94u, + int64 = 95u, + float64 = 96u, + complex80 = 97u, + import_ = 98u, + delegate_ = 99u, + function_ = 100u, + mixin_ = 101u, + in_ = 102u, + break_ = 103u, + continue_ = 104u, + goto_ = 105u, + scope_ = 106u, + traits = 107u, + overloadSet = 108u, + line = 109u, + file = 110u, + fileFullPath = 111u, + moduleString = 112u, + functionString = 113u, + prettyFunction = 114u, + pow = 115u, + powAssign = 116u, + vector = 117u, + voidExpression = 118u, + cantExpression = 119u, + showCtfeContext = 120u, + objcClassReference = 121u, + vectorArray = 122u, + compoundLiteral = 123u, + _Generic_ = 124u, + interval = 125u, + loweredAssignExp = 126u, +}; + +struct complex_t final +{ + _d_real re; + _d_real im; + complex_t() = delete; + complex_t(_d_real re); + complex_t(_d_real re, _d_real im); + int32_t opEquals(complex_t y) const; +}; + +template +struct Optional final +{ + T value; + bool present; + Optional(T value); + static Optional create(T val); + bool isPresent() const; + bool isEmpty() const; + T get(); + bool hasValue(T exp) const; + Optional() + { + } +}; + enum class OwnedBy : uint8_t { code = 0u, @@ -2282,61 +2137,26 @@ struct ArgumentList final names() { } - ArgumentList(Array* arguments, Array* names = nullptr) : - arguments(arguments), - names(names) - {} -}; - -enum : bool { LOGSEMANTIC = false }; - -enum class Modifiable -{ - no = 0, - yes = 1, - initialization = 2, -}; - -enum class ModifyFlags -{ - none = 0, - noError = 1, - fieldAssign = 2, -}; - -struct UnionExp final -{ - #pragma pack(push, 8) -private: - union _AnonStruct_u - { - char exp[29LLU]; - char integerexp[40LLU]; - char errorexp[29LLU]; - char realexp[48LLU]; - char complexexp[64LLU]; - char symoffexp[64LLU]; - char stringexp[51LLU]; - char arrayliteralexp[48LLU]; - char assocarrayliteralexp[56LLU]; - char structliteralexp[76LLU]; - char compoundliteralexp[40LLU]; - char nullexp[29LLU]; - char dotvarexp[49LLU]; - char addrexp[40LLU]; - char indexexp[74LLU]; - char sliceexp[65LLU]; - char vectorexp[53LLU]; - }; - #pragma pack(pop) - - // Ignoring var u alignment 8 - _AnonStruct_u u; -public: - UnionExp() : - u() - { - } + ArgumentList(Array* arguments, Array* names = nullptr) : + arguments(arguments), + names(names) + {} +}; + +enum : bool { LOGSEMANTIC = false }; + +enum class Modifiable +{ + no = 0, + yes = 1, + initialization = 2, +}; + +enum class ModifyFlags +{ + none = 0, + noError = 1, + fieldAssign = 2, }; enum : int32_t { WANTexpand = 1 }; @@ -4745,6 +4565,41 @@ extern Type* merge(Type* type); extern Type* typeSemantic(Type* type, const Loc& loc, Scope* sc); +struct UnionExp final +{ + #pragma pack(push, 8) +private: + union _AnonStruct_u + { + char exp[29LLU]; + char integerexp[40LLU]; + char errorexp[29LLU]; + char realexp[48LLU]; + char complexexp[64LLU]; + char symoffexp[64LLU]; + char stringexp[51LLU]; + char arrayliteralexp[48LLU]; + char assocarrayliteralexp[56LLU]; + char structliteralexp[76LLU]; + char compoundliteralexp[40LLU]; + char nullexp[29LLU]; + char dotvarexp[49LLU]; + char addrexp[40LLU]; + char indexexp[74LLU]; + char sliceexp[65LLU]; + char vectorexp[53LLU]; + }; + #pragma pack(pop) + + // Ignoring var u alignment 8 + _AnonStruct_u u; +public: + UnionExp() : + u() + { + } +}; + enum class MODFlags { none = 0, @@ -4961,12 +4816,14 @@ struct ASTCodegen final using BinAssignExp = ::BinAssignExp; using BinExp = ::BinExp; using BlitExp = ::BlitExp; + using CTFEExp = ::CTFEExp; using CallExp = ::CallExp; using CastExp = ::CastExp; using CatAssignExp = ::CatAssignExp; using CatDcharAssignExp = ::CatDcharAssignExp; using CatElemAssignExp = ::CatElemAssignExp; using CatExp = ::CatExp; + using ClassReferenceExp = ::ClassReferenceExp; using CmpExp = ::CmpExp; using ComExp = ::ComExp; using CommaExp = ::CommaExp; @@ -5052,13 +4909,13 @@ struct ASTCodegen final using TemplateExp = ::TemplateExp; using ThisExp = ::ThisExp; using ThrowExp = ::ThrowExp; + using ThrownExceptionExp = ::ThrownExceptionExp; using TraitsExp = ::TraitsExp; using TupleExp = ::TupleExp; using TypeExp = ::TypeExp; using TypeidExp = ::TypeidExp; using UAddExp = ::UAddExp; using UnaExp = ::UnaExp; - using UnionExp = ::UnionExp; using UshrAssignExp = ::UshrAssignExp; using UshrExp = ::UshrExp; using VarExp = ::VarExp; @@ -5067,7 +4924,6 @@ struct ASTCodegen final using VoidInitExp = ::VoidInitExp; using XorAssignExp = ::XorAssignExp; using XorExp = ::XorExp; - using emplaceExp = ::emplaceExp; using AttributeViolation = ::AttributeViolation; using BUILTIN = ::BUILTIN; using CtorDeclaration = ::CtorDeclaration; @@ -5185,9 +5041,8 @@ struct ASTCodegen final using WhileStatement = ::WhileStatement; using WithStatement = ::WithStatement; using StaticAssert = ::StaticAssert; - using CTFEExp = ::CTFEExp; - using ClassReferenceExp = ::ClassReferenceExp; - using ThrownExceptionExp = ::ThrownExceptionExp; + using UnionExp = ::UnionExp; + using emplaceExp = ::emplaceExp; typedef UserAttributeDeclaration* UserAttributeDeclaration; typedef Ensure Ensure; typedef ErrorExp* ErrorExp; @@ -5833,29 +5688,6 @@ extern const char* cppTypeInfoMangleDMC(Dsymbol* s); extern FileName preprocess(FileName csrcfile, const Loc& loc, bool& ifile, OutBuffer* defines); -class ClassReferenceExp final : public Expression -{ -public: - StructLiteralExp* value; - ClassDeclaration* originalClass(); - int32_t findFieldIndexByName(VarDeclaration* v); - void accept(Visitor* v) override; -}; - -class ThrownExceptionExp final : public Expression -{ -public: - ClassReferenceExp* thrown; - const char* toChars() const override; - void accept(Visitor* v) override; -}; - -class CTFEExp final : public Expression -{ -public: - const char* toChars() const override; -}; - extern MATCH implicitConvTo(Expression* e, Type* t); struct BaseClass final @@ -7017,6 +6849,151 @@ class VersionSymbol final : public Dsymbol extern void expandTuples(Array* exps, Array* names = nullptr); +class Expression : public ASTNode +{ +public: + Type* type; + Loc loc; + const EXP op; + size_t size() const; + static void _init(); + static void deinitialize(); + virtual Expression* syntaxCopy(); + DYNCAST dyncast() const final override; + const char* toChars() const override; + virtual dinteger_t toInteger(); + virtual uinteger_t toUInteger(); + virtual _d_real toReal(); + virtual _d_real toImaginary(); + virtual complex_t toComplex(); + virtual StringExp* toStringExp(); + virtual bool isLvalue(); + virtual bool checkType(); + virtual bool checkValue(); + Expression* addressOf(); + Expression* deref(); + Expression* optimize(int32_t result, bool keepLvalue = false); + int32_t isConst(); + virtual bool isIdentical(const Expression* const e) const; + virtual Optional toBool(); + virtual bool hasCode(); + IntegerExp* isIntegerExp(); + ErrorExp* isErrorExp(); + VoidInitExp* isVoidInitExp(); + RealExp* isRealExp(); + ComplexExp* isComplexExp(); + IdentifierExp* isIdentifierExp(); + DollarExp* isDollarExp(); + DsymbolExp* isDsymbolExp(); + ThisExp* isThisExp(); + SuperExp* isSuperExp(); + NullExp* isNullExp(); + StringExp* isStringExp(); + TupleExp* isTupleExp(); + ArrayLiteralExp* isArrayLiteralExp(); + AssocArrayLiteralExp* isAssocArrayLiteralExp(); + StructLiteralExp* isStructLiteralExp(); + CompoundLiteralExp* isCompoundLiteralExp(); + TypeExp* isTypeExp(); + ScopeExp* isScopeExp(); + TemplateExp* isTemplateExp(); + NewExp* isNewExp(); + NewAnonClassExp* isNewAnonClassExp(); + SymOffExp* isSymOffExp(); + VarExp* isVarExp(); + OverExp* isOverExp(); + FuncExp* isFuncExp(); + DeclarationExp* isDeclarationExp(); + TypeidExp* isTypeidExp(); + TraitsExp* isTraitsExp(); + HaltExp* isHaltExp(); + IsExp* isExp(); + MixinExp* isMixinExp(); + ImportExp* isImportExp(); + AssertExp* isAssertExp(); + ThrowExp* isThrowExp(); + DotIdExp* isDotIdExp(); + DotTemplateExp* isDotTemplateExp(); + DotVarExp* isDotVarExp(); + DotTemplateInstanceExp* isDotTemplateInstanceExp(); + DelegateExp* isDelegateExp(); + DotTypeExp* isDotTypeExp(); + CallExp* isCallExp(); + AddrExp* isAddrExp(); + PtrExp* isPtrExp(); + NegExp* isNegExp(); + UAddExp* isUAddExp(); + ComExp* isComExp(); + NotExp* isNotExp(); + DeleteExp* isDeleteExp(); + CastExp* isCastExp(); + VectorExp* isVectorExp(); + VectorArrayExp* isVectorArrayExp(); + SliceExp* isSliceExp(); + ArrayLengthExp* isArrayLengthExp(); + ArrayExp* isArrayExp(); + DotExp* isDotExp(); + CommaExp* isCommaExp(); + IntervalExp* isIntervalExp(); + DelegatePtrExp* isDelegatePtrExp(); + DelegateFuncptrExp* isDelegateFuncptrExp(); + IndexExp* isIndexExp(); + PostExp* isPostExp(); + PreExp* isPreExp(); + AssignExp* isAssignExp(); + LoweredAssignExp* isLoweredAssignExp(); + ConstructExp* isConstructExp(); + BlitExp* isBlitExp(); + AddAssignExp* isAddAssignExp(); + MinAssignExp* isMinAssignExp(); + MulAssignExp* isMulAssignExp(); + DivAssignExp* isDivAssignExp(); + ModAssignExp* isModAssignExp(); + AndAssignExp* isAndAssignExp(); + OrAssignExp* isOrAssignExp(); + XorAssignExp* isXorAssignExp(); + PowAssignExp* isPowAssignExp(); + ShlAssignExp* isShlAssignExp(); + ShrAssignExp* isShrAssignExp(); + UshrAssignExp* isUshrAssignExp(); + CatAssignExp* isCatAssignExp(); + CatElemAssignExp* isCatElemAssignExp(); + CatDcharAssignExp* isCatDcharAssignExp(); + AddExp* isAddExp(); + MinExp* isMinExp(); + CatExp* isCatExp(); + MulExp* isMulExp(); + DivExp* isDivExp(); + ModExp* isModExp(); + PowExp* isPowExp(); + ShlExp* isShlExp(); + ShrExp* isShrExp(); + UshrExp* isUshrExp(); + AndExp* isAndExp(); + OrExp* isOrExp(); + XorExp* isXorExp(); + LogicalExp* isLogicalExp(); + InExp* isInExp(); + RemoveExp* isRemoveExp(); + EqualExp* isEqualExp(); + IdentityExp* isIdentityExp(); + CondExp* isCondExp(); + GenericExp* isGenericExp(); + DefaultInitExp* isDefaultInitExp(); + FileInitExp* isFileInitExp(); + LineInitExp* isLineInitExp(); + ModuleInitExp* isModuleInitExp(); + FuncInitExp* isFuncInitExp(); + PrettyFuncInitExp* isPrettyFuncInitExp(); + ObjcClassReferenceExp* isObjcClassReferenceExp(); + ClassReferenceExp* isClassReferenceExp(); + ThrownExceptionExp* isThrownExceptionExp(); + UnaExp* isUnaExp(); + BinExp* isBinExp(); + BinAssignExp* isBinAssignExp(); + void accept(Visitor* v) override; +}; + class IntegerExp final : public Expression { dinteger_t value; @@ -7968,6 +7945,30 @@ class PrettyFuncInitExp final : public DefaultInitExp void accept(Visitor* v) override; }; +class ClassReferenceExp final : public Expression +{ +public: + StructLiteralExp* value; + ClassDeclaration* originalClass(); + int32_t getFieldIndex(Type* fieldtype, uint32_t fieldoffset); + int32_t findFieldIndexByName(VarDeclaration* v); + void accept(Visitor* v) override; +}; + +class CTFEExp final : public Expression +{ +public: + const char* toChars() const override; +}; + +class ThrownExceptionExp final : public Expression +{ +public: + ClassReferenceExp* thrown; + const char* toChars() const override; + void accept(Visitor* v) override; +}; + class ObjcClassReferenceExp final : public Expression { public: diff --git a/tests/dmd/unit/deinitialization.d b/tests/dmd/unit/deinitialization.d index d3458802af9..e96d9558ce9 100644 --- a/tests/dmd/unit/deinitialization.d +++ b/tests/dmd/unit/deinitialization.d @@ -123,8 +123,7 @@ unittest @("Expression.deinitialize") unittest { - import dmd.ctfeexpr : CTFEExp; - import dmd.expression : Expression; + import dmd.expression : Expression, CTFEExp; static void assertInitialState() { From 21c1d2ecc4e429cbedd82be0beb5c0d54b3741f0 Mon Sep 17 00:00:00 2001 From: RazvanN7 Date: Tue, 7 Nov 2023 13:53:52 +0200 Subject: [PATCH 011/215] Break expression.d dependency on optimize.d --- dmd/cond.d | 1 + dmd/dcast.d | 1 + dmd/dmangle.d | 1 + dmd/dsymbolsem.d | 1 + dmd/dtemplate.d | 1 + dmd/expression.d | 6 ------ dmd/frontend.h | 1 - dmd/hdrgen.d | 1 + dmd/initsem.d | 1 + dmd/opover.d | 1 + dmd/optimize.d | 16 ++++++++-------- dmd/semantic3.d | 1 + dmd/statementsem.d | 1 + dmd/staticcond.d | 1 + dmd/traits.d | 1 + dmd/typesem.d | 1 + 16 files changed, 21 insertions(+), 15 deletions(-) diff --git a/dmd/cond.d b/dmd/cond.d index a8d099433a2..568b639e0b6 100644 --- a/dmd/cond.d +++ b/dmd/cond.d @@ -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; diff --git a/dmd/dcast.d b/dmd/dcast.d index f769473f591..eb3890bb58f 100644 --- a/dmd/dcast.d +++ b/dmd/dcast.d @@ -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; diff --git a/dmd/dmangle.d b/dmd/dmangle.d index c58b5857482..2bedccb71c1 100644 --- a/dmd/dmangle.d +++ b/dmd/dmangle.d @@ -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; diff --git a/dmd/dsymbolsem.d b/dmd/dsymbolsem.d index 397c5e53d7f..ce1a8d69dc2 100644 --- a/dmd/dsymbolsem.d +++ b/dmd/dsymbolsem.d @@ -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; diff --git a/dmd/dtemplate.d b/dmd/dtemplate.d index 883f4ac94cf..4cf1bae7537 100644 --- a/dmd/dtemplate.d +++ b/dmd/dtemplate.d @@ -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; diff --git a/dmd/expression.d b/dmd/expression.d index e98a8ee0c30..47902213504 100644 --- a/dmd/expression.d +++ b/dmd/expression.d @@ -39,7 +39,6 @@ import dmd.identifier; import dmd.init; import dmd.location; import dmd.mtype; -import dmd.optimize; import dmd.root.complex; import dmd.root.ctfloat; import dmd.common.outbuffer; @@ -705,11 +704,6 @@ extern (C++) abstract class Expression : ASTNode return this; } - final Expression optimize(int result, bool keepLvalue = false) - { - return Expression_optimize(this, result, keepLvalue); - } - final int isConst() { //printf("Expression::isConst(): %s\n", e.toChars()); diff --git a/dmd/frontend.h b/dmd/frontend.h index 0095cb087f4..48705f264e7 100644 --- a/dmd/frontend.h +++ b/dmd/frontend.h @@ -6872,7 +6872,6 @@ class Expression : public ASTNode virtual bool checkValue(); Expression* addressOf(); Expression* deref(); - Expression* optimize(int32_t result, bool keepLvalue = false); int32_t isConst(); virtual bool isIdentical(const Expression* const e) const; virtual Optional toBool(); diff --git a/dmd/hdrgen.d b/dmd/hdrgen.d index d935bd3480b..8325081dbd2 100644 --- a/dmd/hdrgen.d +++ b/dmd/hdrgen.d @@ -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; diff --git a/dmd/initsem.d b/dmd/initsem.d index 632c0d0a682..139db0f59e9 100644 --- a/dmd/initsem.d +++ b/dmd/initsem.d @@ -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; diff --git a/dmd/opover.d b/dmd/opover.d index addcd0103d0..b445b7b707b 100644 --- a/dmd/opover.d +++ b/dmd/opover.d @@ -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; diff --git a/dmd/optimize.d b/dmd/optimize.d index 0065b016f83..69028fac21d 100644 --- a/dmd/optimize.d +++ b/dmd/optimize.d @@ -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); diff --git a/dmd/semantic3.d b/dmd/semantic3.d index 0b0ca916db2..8af79bfc2d5 100644 --- a/dmd/semantic3.d +++ b/dmd/semantic3.d @@ -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; diff --git a/dmd/statementsem.d b/dmd/statementsem.d index d43d915e2e3..fe447a1c583 100644 --- a/dmd/statementsem.d +++ b/dmd/statementsem.d @@ -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; diff --git a/dmd/staticcond.d b/dmd/staticcond.d index 923f1a99e80..1d18de31829 100644 --- a/dmd/staticcond.d +++ b/dmd/staticcond.d @@ -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; diff --git a/dmd/traits.d b/dmd/traits.d index 7489f99aa90..79df7fde02b 100644 --- a/dmd/traits.d +++ b/dmd/traits.d @@ -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; diff --git a/dmd/typesem.d b/dmd/typesem.d index 4618a6754ae..686f1d19c9b 100644 --- a/dmd/typesem.d +++ b/dmd/typesem.d @@ -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; From b5e90c8c02875ed3b7e2262f042ac61152f29d12 Mon Sep 17 00:00:00 2001 From: Walter Bright Date: Thu, 9 Nov 2023 00:20:59 -0800 Subject: [PATCH 012/215] fix Issue 24069 - ImportC does not parse function pointer as parameter without name (dlang/dmd!15790) --- dmd/cparse.d | 24 ++++++++++++++++++++++-- dmd/lexer.d | 18 ++++++++++++++++++ tests/dmd/compilable/test24069.i | 17 +++++++++++++++++ tests/dmd/fail_compilation/failcstuff1.c | 19 +++++++++++++------ tests/dmd/fail_compilation/test22102.c | 7 ++++--- tests/dmd/fail_compilation/test22339.c | 4 ++++ tests/dmd/fail_compilation/test23037.c | 8 +++++--- tests/dmd/fail_compilation/testTypeof.c | 6 ++++-- 8 files changed, 87 insertions(+), 16 deletions(-) create mode 100644 tests/dmd/compilable/test24069.i diff --git a/dmd/cparse.d b/dmd/cparse.d index b8e80527ec7..f0c834972d6 100644 --- a/dmd/cparse.d +++ b/dmd/cparse.d @@ -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) diff --git a/dmd/lexer.d b/dmd/lexer.d index a1214b2623e..b8faec76d60 100644 --- a/dmd/lexer.d +++ b/dmd/lexer.d @@ -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"); + } } diff --git a/tests/dmd/compilable/test24069.i b/tests/dmd/compilable/test24069.i new file mode 100644 index 00000000000..881934ffb98 --- /dev/null +++ b/tests/dmd/compilable/test24069.i @@ -0,0 +1,17 @@ + +// https://issues.dlang.org/show_bug.cgi?id=24069 + +typedef void (*fp_t)(int*); + +float parse1(void f(int*)); // float (void (*)(int *)) +float parse2(void (int*)); +typedef int Dat; +float parse3(void (Dat*)); + +void test(float i) +{ + fp_t x; + parse1(x); + parse2(x); + parse3(x); +} diff --git a/tests/dmd/fail_compilation/failcstuff1.c b/tests/dmd/fail_compilation/failcstuff1.c index 39524cb6a12..0e6e1c85692 100644 --- a/tests/dmd/fail_compilation/failcstuff1.c +++ b/tests/dmd/fail_compilation/failcstuff1.c @@ -17,11 +17,20 @@ fail_compilation/failcstuff1.c(206): Error: storage class not allowed in specifi fail_compilation/failcstuff1.c(207): Error: storage class not allowed in specifier-qualified-list fail_compilation/failcstuff1.c(208): Error: storage class not allowed in specifier-qualified-list fail_compilation/failcstuff1.c(251): Error: identifier or `(` expected +fail_compilation/failcstuff1.c(251): Error: expected identifier for declarator +fail_compilation/failcstuff1.c(251): Error: expected identifier for declaration fail_compilation/failcstuff1.c(252): Error: identifier or `(` expected +fail_compilation/failcstuff1.c(252): Error: expected identifier for declarator +fail_compilation/failcstuff1.c(252): Error: expected identifier for declaration fail_compilation/failcstuff1.c(253): Error: identifier or `(` expected +fail_compilation/failcstuff1.c(253): Error: expected identifier for declarator +fail_compilation/failcstuff1.c(253): Error: expected identifier for declaration fail_compilation/failcstuff1.c(258): Error: identifier or `(` expected +fail_compilation/failcstuff1.c(258): Error: expected identifier for declarator fail_compilation/failcstuff1.c(259): Error: identifier or `(` expected +fail_compilation/failcstuff1.c(259): Error: expected identifier for declarator fail_compilation/failcstuff1.c(260): Error: identifier or `(` expected +fail_compilation/failcstuff1.c(260): Error: expected identifier for declarator fail_compilation/failcstuff1.c(301): Error: illegal type combination fail_compilation/failcstuff1.c(352): Error: found `2` when expecting `:` fail_compilation/failcstuff1.c(352): Error: found `:` instead of statement @@ -39,12 +48,10 @@ fail_compilation/failcstuff1.c(460): Error: variable length arrays are not suppo fail_compilation/failcstuff1.c(460): Error: variable length array used outside of function prototype fail_compilation/failcstuff1.c(461): Error: array type has incomplete element type `int[0]` fail_compilation/failcstuff1.c(462): Error: `=`, `;` or `,` expected to end declaration instead of `const` -fail_compilation/failcstuff1.c(502): Error: identifier or `(` expected -fail_compilation/failcstuff1.c(502): Error: found `;` when expecting `)` -fail_compilation/failcstuff1.c(503): Error: `=`, `;` or `,` expected to end declaration instead of `int` -fail_compilation/failcstuff1.c(504): Error: identifier or `(` expected -fail_compilation/failcstuff1.c(504): Error: found `;` when expecting `)` -fail_compilation/failcstuff1.c(505): Error: `=`, `;` or `,` expected to end declaration instead of `int` +fail_compilation/failcstuff1.c(502): Error: no type-specifier for parameter +fail_compilation/failcstuff1.c(502): Error: found `0` when expecting `,` +fail_compilation/failcstuff1.c(502): Error: expected identifier for declarator +fail_compilation/failcstuff1.c(504): Error: expected identifier for declarator fail_compilation/failcstuff1.c(551): Error: missing comma or semicolon after declaration of `pluto`, found `p` instead fail_compilation/failcstuff1.c(601): Error: `=`, `;` or `,` expected to end declaration instead of `'s'` fail_compilation/failcstuff1.c(652): Error: multiple storage classes in declaration specifiers diff --git a/tests/dmd/fail_compilation/test22102.c b/tests/dmd/fail_compilation/test22102.c index 25596b6e18d..8714d633209 100644 --- a/tests/dmd/fail_compilation/test22102.c +++ b/tests/dmd/fail_compilation/test22102.c @@ -1,8 +1,9 @@ /* TEST_OUTPUT: --- -fail_compilation/test22102.c(254): Error: identifier or `(` expected -fail_compilation/test22102.c(254): Error: found `;` when expecting `)` -fail_compilation/test22102.c(255): Error: `=`, `;` or `,` expected to end declaration instead of `int22102` +fail_compilation/test22102.c(254): Error: expected identifier for declarator +fail_compilation/test22102.c(255): Error: no type-specifier for parameter +fail_compilation/test22102.c(255): Error: found `0` when expecting `,` +fail_compilation/test22102.c(255): Error: expected identifier for declarator --- */ /***************************************************/ diff --git a/tests/dmd/fail_compilation/test22339.c b/tests/dmd/fail_compilation/test22339.c index 14e4c7f2e89..f46f35805c8 100644 --- a/tests/dmd/fail_compilation/test22339.c +++ b/tests/dmd/fail_compilation/test22339.c @@ -3,10 +3,14 @@ fail_compilation/test22339.c(101): Error: expression expected, not `.` fail_compilation/test22339.c(101): Error: found `'a'` when expecting `}` fail_compilation/test22339.c(101): Error: identifier or `(` expected +fail_compilation/test22339.c(101): Error: expected identifier for declarator +fail_compilation/test22339.c(101): Error: expected identifier for declaration fail_compilation/test22339.c(101): Error: `=`, `;` or `,` expected to end declaration instead of `}` fail_compilation/test22339.c(102): Error: expression expected, not `.` fail_compilation/test22339.c(102): Error: found `'\x03'` when expecting `}` fail_compilation/test22339.c(102): Error: identifier or `(` expected +fail_compilation/test22339.c(102): Error: expected identifier for declarator +fail_compilation/test22339.c(102): Error: expected identifier for declaration fail_compilation/test22339.c(102): Error: `=`, `;` or `,` expected to end declaration instead of `}` --- */ diff --git a/tests/dmd/fail_compilation/test23037.c b/tests/dmd/fail_compilation/test23037.c index 98beb350ec4..bc2594926c6 100644 --- a/tests/dmd/fail_compilation/test23037.c +++ b/tests/dmd/fail_compilation/test23037.c @@ -11,9 +11,11 @@ fail_compilation/test23037.c(202): Error: no type-specifier for struct member fail_compilation/test23037.c(203): Error: type-specifier omitted before declaration of `x` fail_compilation/test23037.c(204): Error: type-specifier omitted for parameter `x` fail_compilation/test23037.c(205): Error: type-specifier omitted before bit field declaration of `x` -fail_compilation/test23037.c(206): Error: no type-specifier for declarator -fail_compilation/test23037.c(206): Error: found `;` when expecting `)` -fail_compilation/test23037.c(207): Error: `=`, `;` or `,` expected to end declaration instead of `const` +fail_compilation/test23037.c(206): Error: expected identifier for declarator +fail_compilation/test23037.c(206): Error: expected identifier for declaration +fail_compilation/test23037.c(207): Error: no type-specifier for declarator +fail_compilation/test23037.c(207): Error: expected identifier for declarator +fail_compilation/test23037.c(207): Error: expected identifier for declaration --- */ diff --git a/tests/dmd/fail_compilation/testTypeof.c b/tests/dmd/fail_compilation/testTypeof.c index 4c02b329eba..dd7781fca5f 100644 --- a/tests/dmd/fail_compilation/testTypeof.c +++ b/tests/dmd/fail_compilation/testTypeof.c @@ -1,7 +1,9 @@ /* TEST_OUTPUT: --- -fail_compilation/testTypeof.c(8): Error: `typeof` operator expects an expression or type name in parentheses -fail_compilation/testTypeof.c(8): Error: identifier or `(` expected +fail_compilation/testTypeof.c(10): Error: `typeof` operator expects an expression or type name in parentheses +fail_compilation/testTypeof.c(10): Error: identifier or `(` expected +fail_compilation/testTypeof.c(10): Error: expected identifier for declarator +fail_compilation/testTypeof.c(10): Error: expected identifier for declaration --- */ From c698cccf94cc11576fcb5fa24acaa420a86ab1dd Mon Sep 17 00:00:00 2001 From: Razvan Nitu Date: Thu, 9 Nov 2023 17:39:21 +0200 Subject: [PATCH 013/215] Move a couple of functions out of dsymbol.d (dlang/dmd!15789) --- dmd/dsymbol.d | 91 -------------------------------------------------- dmd/dsymbol.h | 1 - dmd/frontend.h | 3 +- dmd/typesem.d | 58 ++++++++++++++++++++++++++++++++ dmd/typinf.d | 36 ++++++++++++++++++++ dmd/typinf.h | 3 ++ 6 files changed, 99 insertions(+), 93 deletions(-) diff --git a/dmd/dsymbol.d b/dmd/dsymbol.d index 914213c1e57..a662e5a12a6 100644 --- a/dmd/dsymbol.d +++ b/dmd/dsymbol.d @@ -45,7 +45,6 @@ import dmd.lexer; import dmd.location; import dmd.mtype; import dmd.nspace; -import dmd.opover; import dmd.root.aav; import dmd.root.rmem; import dmd.rootobject; @@ -875,64 +874,6 @@ extern (C++) class Dsymbol : ASTNode return speller!symbol_search_fp(ident.toString()); } - /*************************************** - * Search for identifier id as a member of `this`. - * `id` may be a template instance. - * - * Params: - * loc = location to print the error messages - * sc = the scope where the symbol is located - * id = the id of the symbol - * flags = the search flags which can be `SearchLocalsOnly` or `IgnorePrivateImports` - * - * Returns: - * symbol found, NULL if not - */ - extern (D) final Dsymbol searchX(const ref Loc loc, Scope* sc, RootObject id, int flags) - { - //printf("Dsymbol::searchX(this=%p,%s, ident='%s')\n", this, toChars(), ident.toChars()); - Dsymbol s = toAlias(); - Dsymbol sm; - if (Declaration d = s.isDeclaration()) - { - if (d.inuse) - { - .error(loc, "circular reference to `%s`", d.toPrettyChars()); - return null; - } - } - switch (id.dyncast()) - { - case DYNCAST.identifier: - sm = s.search(loc, cast(Identifier)id, flags); - break; - case DYNCAST.dsymbol: - { - // It's a template instance - //printf("\ttemplate instance id\n"); - Dsymbol st = cast(Dsymbol)id; - TemplateInstance ti = st.isTemplateInstance(); - sm = s.search(loc, ti.name); - if (!sm) - return null; - sm = sm.toAlias(); - TemplateDeclaration td = sm.isTemplateDeclaration(); - if (!td) - return null; // error but handled later - ti.tempdecl = td; - if (!ti.semanticRun) - ti.dsymbolSemantic(sc); - sm = ti.toAlias(); - break; - } - case DYNCAST.type: - case DYNCAST.expression: - default: - assert(0); - } - return sm; - } - bool overloadInsert(Dsymbol s) { //printf("Dsymbol::overloadInsert('%s')\n", s.toChars()); @@ -1704,38 +1645,6 @@ public: return "ScopeDsymbol"; } - /******************************************* - * Look for member of the form: - * const(MemberInfo)[] getMembers(string); - * Returns NULL if not found - */ - final FuncDeclaration findGetMembers() - { - Dsymbol s = search_function(this, Id.getmembers); - FuncDeclaration fdx = s ? s.isFuncDeclaration() : null; - version (none) - { - // Finish - __gshared TypeFunction tfgetmembers; - if (!tfgetmembers) - { - Scope sc; - sc.eSink = global.errorSink; - auto parameters = new Parameters(); - Parameters* p = new Parameter(STC.in_, Type.tchar.constOf().arrayOf(), null, null); - parameters.push(p); - Type tret = null; - TypeFunction tf = new TypeFunction(parameters, tret, VarArg.none, LINK.d); - tfgetmembers = tf.dsymbolSemantic(Loc.initial, &sc).isTypeFunction(); - } - if (fdx) - fdx = fdx.overloadExactMatch(tfgetmembers); - } - if (fdx && fdx.isVirtual()) - fdx = null; - return fdx; - } - /******************************** * Insert Dsymbol in table. * Params: diff --git a/dmd/dsymbol.h b/dmd/dsymbol.h index 027897532d1..243b0d78419 100644 --- a/dmd/dsymbol.h +++ b/dmd/dsymbol.h @@ -346,7 +346,6 @@ class ScopeDsymbol : public Dsymbol bool isforwardRef() override final; static void multiplyDefined(const Loc &loc, Dsymbol *s1, Dsymbol *s2); const char *kind() const override; - FuncDeclaration *findGetMembers(); virtual Dsymbol *symtabInsert(Dsymbol *s); virtual Dsymbol *symtabLookup(Dsymbol *s, Identifier *id); bool hasStaticCtorOrDtor() override; diff --git a/dmd/frontend.h b/dmd/frontend.h index 48705f264e7..9039320de41 100644 --- a/dmd/frontend.h +++ b/dmd/frontend.h @@ -632,7 +632,6 @@ class ScopeDsymbol : public Dsymbol bool isforwardRef() final override; static void multiplyDefined(const Loc& loc, Dsymbol* s1, Dsymbol* s2); const char* kind() const override; - FuncDeclaration* findGetMembers(); virtual Dsymbol* symtabInsert(Dsymbol* s); virtual Dsymbol* symtabLookup(Dsymbol* s, Identifier* id); bool hasStaticCtorOrDtor() override; @@ -8228,6 +8227,8 @@ extern bool isSpeculativeType(Type* t); extern bool builtinTypeInfo(Type* t); +extern FuncDeclaration* findGetMembers(ScopeDsymbol* dsym); + class SemanticTimeTransitiveVisitor : public SemanticTimePermissiveVisitor { public: diff --git a/dmd/typesem.d b/dmd/typesem.d index 686f1d19c9b..ef2aa1ec462 100644 --- a/dmd/typesem.d +++ b/dmd/typesem.d @@ -372,6 +372,64 @@ private void resolveHelper(TypeQualified mt, const ref Loc loc, Scope* sc, Dsymb pt = t.merge(); } +/*************************************** + * Search for identifier id as a member of `this`. + * `id` may be a template instance. + * + * Params: + * loc = location to print the error messages + * sc = the scope where the symbol is located + * id = the id of the symbol + * flags = the search flags which can be `SearchLocalsOnly` or `IgnorePrivateImports` + * + * Returns: + * symbol found, NULL if not + */ +private Dsymbol searchX(Dsymbol dsym, const ref Loc loc, Scope* sc, RootObject id, int flags) +{ + //printf("Dsymbol::searchX(this=%p,%s, ident='%s')\n", this, toChars(), ident.toChars()); + Dsymbol s = dsym.toAlias(); + Dsymbol sm; + if (Declaration d = s.isDeclaration()) + { + if (d.inuse) + { + .error(loc, "circular reference to `%s`", d.toPrettyChars()); + return null; + } + } + switch (id.dyncast()) + { + case DYNCAST.identifier: + sm = s.search(loc, cast(Identifier)id, flags); + break; + case DYNCAST.dsymbol: + { + // It's a template instance + //printf("\ttemplate instance id\n"); + Dsymbol st = cast(Dsymbol)id; + TemplateInstance ti = st.isTemplateInstance(); + sm = s.search(loc, ti.name); + if (!sm) + return null; + sm = sm.toAlias(); + TemplateDeclaration td = sm.isTemplateDeclaration(); + if (!td) + return null; // error but handled later + ti.tempdecl = td; + if (!ti.semanticRun) + ti.dsymbolSemantic(sc); + sm = ti.toAlias(); + break; + } + case DYNCAST.type: + case DYNCAST.expression: + default: + assert(0); + } + return sm; +} + /****************************************** * We've mistakenly parsed `t` as a type. * Redo `t` as an Expression only if there are no type modifiers. diff --git a/dmd/typinf.d b/dmd/typinf.d index 5890fa1b61d..0d0ae35df91 100644 --- a/dmd/typinf.d +++ b/dmd/typinf.d @@ -15,13 +15,17 @@ import dmd.astenums; import dmd.declaration; import dmd.dmodule; import dmd.dscope; +import dmd.dsymbol; import dmd.dclass; import dmd.dstruct; import dmd.errors; import dmd.expression; +import dmd.func; import dmd.globals; +import dmd.id; import dmd.location; import dmd.mtype; +import dmd.opover; import core.stdc.stdio; /**************************************************** @@ -271,3 +275,35 @@ extern (C++) bool builtinTypeInfo(Type t) } return false; } + +/******************************************* + * Look for member of the form: + * const(MemberInfo)[] getMembers(string); + * Returns NULL if not found + */ +extern(C++) FuncDeclaration findGetMembers(ScopeDsymbol dsym) +{ + Dsymbol s = search_function(dsym, Id.getmembers); + FuncDeclaration fdx = s ? s.isFuncDeclaration() : null; + version (none) + { + // Finish + __gshared TypeFunction tfgetmembers; + if (!tfgetmembers) + { + Scope sc; + sc.eSink = global.errorSink; + auto parameters = new Parameters(); + Parameters* p = new Parameter(STC.in_, Type.tchar.constOf().arrayOf(), null, null); + parameters.push(p); + Type tret = null; + TypeFunction tf = new TypeFunction(parameters, tret, VarArg.none, LINK.d); + tfgetmembers = tf.dsymbolSemantic(Loc.initial, &sc).isTypeFunction(); + } + if (fdx) + fdx = fdx.overloadExactMatch(tfgetmembers); + } + if (fdx && fdx.isVirtual()) + fdx = null; + return fdx; +} diff --git a/dmd/typinf.h b/dmd/typinf.h index 76f623a0a3e..b5c144fa8ee 100644 --- a/dmd/typinf.h +++ b/dmd/typinf.h @@ -15,8 +15,11 @@ class Expression; class Type; struct Scope; +class FuncDeclaration; +class ScopeDsymbol; bool genTypeInfo(Expression *e, const Loc &loc, Type *torig, Scope *sc); Type *getTypeInfoType(const Loc &loc, Type *t, Scope *sc, bool genObjCode = true); bool isSpeculativeType(Type *t); bool builtinTypeInfo(Type *t); +FuncDeclaration *findGetMembers(ScopeDsymbol *dsym); From 621bd6d5455d18c3482ff7cc46cdacde2c8294d0 Mon Sep 17 00:00:00 2001 From: Denis Feklushkin Date: Sat, 11 Nov 2023 15:42:59 +0300 Subject: [PATCH 014/215] Event.set() -> Event.setIfInitialized() --- .../src/core/internal/gc/impl/conservative/gc.d | 6 +++--- runtime/druntime/src/core/sync/event.d | 12 ++++++++---- 2 files changed, 11 insertions(+), 7 deletions(-) diff --git a/runtime/druntime/src/core/internal/gc/impl/conservative/gc.d b/runtime/druntime/src/core/internal/gc/impl/conservative/gc.d index 39cd30aee16..6f194126e7e 100644 --- a/runtime/druntime/src/core/internal/gc/impl/conservative/gc.d +++ b/runtime/druntime/src/core/internal/gc/impl/conservative/gc.d @@ -3336,7 +3336,7 @@ Lmark: busyThreads.atomicOp!"+="(1); // main thread is busy - evStart.set(); + evStart.setIfInitialized(); debug(PARALLEL_PRINTF) printf("mark %lld roots\n", cast(ulong)(ptop - pbot)); @@ -3438,7 +3438,7 @@ Lmark: stopGC = true; while (atomicLoad(stoppedThreads) < startedThreads && !allThreadsDead) { - evStart.set(); + evStart.setIfInitialized(); evDone.wait(dur!"msecs"(1)); } @@ -3467,7 +3467,7 @@ Lmark: { evStart.wait(); pullFromScanStack(); - evDone.set(); + evDone.setIfInitialized(); } stoppedThreads.atomicOp!"+="(1); } diff --git a/runtime/druntime/src/core/sync/event.d b/runtime/druntime/src/core/sync/event.d index 37951061d93..4e75a9d2a9f 100644 --- a/runtime/druntime/src/core/sync/event.d +++ b/runtime/druntime/src/core/sync/event.d @@ -61,7 +61,7 @@ struct ProcessFile group.create(&doProcess); buffer = std.file.read(filename); - event.set(); + event.setIfInitialized(); group.joinAll(); event.terminate(); } @@ -162,9 +162,13 @@ nothrow @nogc: } } + deprecated void set() + { + setIfInitialized(); + } /// Set the event to "signaled", so that waiting clients are resumed - void set() + void setIfInitialized() { version (Windows) { @@ -302,7 +306,7 @@ private: // auto-reset, initial state false Event ev1 = Event(false, false); assert(!ev1.wait(1.dur!"msecs")); - ev1.set(); + ev1.setIfInitialized(); assert(ev1.wait()); assert(!ev1.wait(1.dur!"msecs")); @@ -336,7 +340,7 @@ unittest auto start = MonoTime.currTime; assert(numRunning == 0); - event.set(); + event.setIfInitialized(); group.joinAll(); assert(numRunning == numThreads); From f4327d809f0d3582b5fc37c90dcce3ca14e46943 Mon Sep 17 00:00:00 2001 From: Denis Feklushkin Date: Sat, 11 Nov 2023 16:04:24 +0300 Subject: [PATCH 015/215] Deprecation message improved --- runtime/druntime/src/core/sync/event.d | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/runtime/druntime/src/core/sync/event.d b/runtime/druntime/src/core/sync/event.d index 4e75a9d2a9f..048607f6ed2 100644 --- a/runtime/druntime/src/core/sync/event.d +++ b/runtime/druntime/src/core/sync/event.d @@ -162,7 +162,7 @@ nothrow @nogc: } } - deprecated void set() + deprecated ("Use setIfInitialized() instead") void set() { setIfInitialized(); } From 43c1a250c3f8f231ebd4d8945056c25f1b2eb8d7 Mon Sep 17 00:00:00 2001 From: mhh Date: Sat, 11 Nov 2023 00:24:12 +0000 Subject: [PATCH 016/215] This commit introduces a member function of `Param` that replaces some duplicated logic across the tree for deciding if unittests are required to build a program (i.e. for a given set of compiler flags) --- dmd/dmodule.d | 2 +- dmd/dsymbolsem.d | 2 +- dmd/expressionsem.d | 2 +- dmd/frontend.h | 1 + dmd/globals.d | 6 ++++++ dmd/iasmgcc.d | 2 +- dmd/statementsem.d | 2 +- dmd/typesem.d | 2 +- 8 files changed, 13 insertions(+), 6 deletions(-) diff --git a/dmd/dmodule.d b/dmd/dmodule.d index 548928a0124..e6dde181fab 100644 --- a/dmd/dmodule.d +++ b/dmd/dmodule.d @@ -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(); diff --git a/dmd/dsymbolsem.d b/dmd/dsymbolsem.d index ce1a8d69dc2..4ef5590d638 100644 --- a/dmd/dsymbolsem.d +++ b/dmd/dsymbolsem.d @@ -1952,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; diff --git a/dmd/expressionsem.d b/dmd/expressionsem.d index b3d753600c4..83ec28b2cc9 100644 --- a/dmd/expressionsem.d +++ b/dmd/expressionsem.d @@ -7401,7 +7401,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor uint errors = global.errors; const len = buf.length; const str = buf.extractChars()[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, exp.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; diff --git a/dmd/frontend.h b/dmd/frontend.h index 9039320de41..d40051b0800 100644 --- a/dmd/frontend.h +++ b/dmd/frontend.h @@ -3062,6 +3062,7 @@ struct Param final _d_dynamicArray< const char > resfile; _d_dynamicArray< const char > exefile; _d_dynamicArray< const char > mapfile; + bool parsingUnittestsRequired(); Param() : obj(true), multiobj(), diff --git a/dmd/globals.d b/dmd/globals.d index 2f6fae3a1ab..8d88207a566 100644 --- a/dmd/globals.d +++ b/dmd/globals.d @@ -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 diff --git a/dmd/iasmgcc.d b/dmd/iasmgcc.d index 5494fecd70c..276152da355 100644 --- a/dmd/iasmgcc.d +++ b/dmd/iasmgcc.d @@ -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. diff --git a/dmd/statementsem.d b/dmd/statementsem.d index fe447a1c583..f8b2c26df7f 100644 --- a/dmd/statementsem.d +++ b/dmd/statementsem.d @@ -4888,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; diff --git a/dmd/typesem.d b/dmd/typesem.d index ef2aa1ec462..bc0ae18eaad 100644 --- a/dmd/typesem.d +++ b/dmd/typesem.d @@ -5068,7 +5068,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; From b2001a47a763544420c561224ae4eb963786f2b9 Mon Sep 17 00:00:00 2001 From: Nick Treleaven Date: Wed, 8 Nov 2023 13:27:10 +0000 Subject: [PATCH 017/215] Add hint when declaring function with TypeCtor --- dmd/dsymbolsem.d | 10 +++++++--- tests/dmd/fail_compilation/fail212.d | 6 +++++- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/dmd/dsymbolsem.d b/dmd/dsymbolsem.d index 4ef5590d638..637edd7bf08 100644 --- a/dmd/dsymbolsem.d +++ b/dmd/dsymbolsem.d @@ -3385,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 } diff --git a/tests/dmd/fail_compilation/fail212.d b/tests/dmd/fail_compilation/fail212.d index 5f308638b9c..780cd8279e5 100644 --- a/tests/dmd/fail_compilation/fail212.d +++ b/tests/dmd/fail_compilation/fail212.d @@ -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 From a1642b51afae007ecbff8383634840c8ceed1af1 Mon Sep 17 00:00:00 2001 From: Dennis Date: Sun, 12 Nov 2023 10:08:22 +0100 Subject: [PATCH 018/215] Refactor `toLvalue` by removing redundant parameter (dlang/dmd!15792) --- dmd/expression.h | 2 +- dmd/expressionsem.d | 52 +++++++++++++++++++++++++-------------------- dmd/frontend.h | 2 +- dmd/inline.d | 2 +- dmd/semantic3.d | 2 +- dmd/typesem.d | 2 +- 6 files changed, 34 insertions(+), 28 deletions(-) diff --git a/dmd/expression.h b/dmd/expression.h index beb913c8895..86675d5df39 100644 --- a/dmd/expression.h +++ b/dmd/expression.h @@ -52,7 +52,7 @@ 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 *e); +Expression *toLvalue(Expression *_this, Scope *sc); Expression *modifiableLvalue(Expression* exp, Scope *sc, Expression *e); typedef unsigned char OwnedBy; diff --git a/dmd/expressionsem.d b/dmd/expressionsem.d index 83ec28b2cc9..abdaf189919 100644 --- a/dmd/expressionsem.d +++ b/dmd/expressionsem.d @@ -3129,7 +3129,7 @@ private bool functionParameters(const ref Loc loc, Scope* sc, ev = new CommaExp(arg.loc, ev, new VarExp(arg.loc, v)); arg = ev.expressionSemantic(sc); } - arg = arg.toLvalue(sc, arg); + arg = arg.toLvalue(sc); // Look for mutable misaligned pointer, etc., in @safe mode err |= checkUnsafeAccess(sc, arg, false, true); @@ -3147,7 +3147,7 @@ private bool functionParameters(const ref Loc loc, Scope* sc, ev = new CommaExp(arg.loc, ev, new VarExp(arg.loc, v)); arg = ev.expressionSemantic(sc); } - arg = arg.toLvalue(sc, arg); + arg = arg.toLvalue(sc); // Look for mutable misaligned pointer, etc., in @safe mode err |= checkUnsafeAccess(sc, arg, false, true); @@ -3166,7 +3166,7 @@ private bool functionParameters(const ref Loc loc, Scope* sc, err |= checkUnsafeAccess(sc, arg, false, true); err |= checkDefCtor(arg.loc, t); // t must be default constructible } - arg = arg.toLvalue(sc, arg); + arg = arg.toLvalue(sc); } else if (p.isLazy()) { @@ -8295,7 +8295,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor else { // `toLvalue` call further below is upon exp.e1, omitting & from the error message - exp.toLvalue(sc, null); + exp.toLvalue(sc); return setError(); } } @@ -8385,7 +8385,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor } } - exp.e1 = exp.e1.toLvalue(sc, null); + exp.e1 = exp.e1.toLvalue(sc); if (exp.e1.op == EXP.error) { result = exp.e1; @@ -15204,11 +15204,21 @@ Expression addDtorHook(Expression e, Scope* sc) } /******************************* -* Give error if we're not an lvalue. -* If we can, convert expression to be an lvalue. + * Try to convert an expression to be an lvalue. + * + * Give error if we're not an lvalue. + * Params: + * _this = expression to convert + * sc = scope + * Returns: converted expression, or `ErrorExp` on error */ -extern(C++) Expression toLvalue(Expression _this, Scope* sc, Expression e) +extern(C++) Expression toLvalue(Expression _this, Scope* sc) { + return toLvalueImpl(_this, sc, _this); +} + +// e = original un-lowered expression for error messages, in case of recursive calls +private Expression toLvalueImpl(Expression _this, Scope* sc, Expression e) { Expression visit(Expression _this) { // BinaryAssignExp does not have an EXP associated @@ -15216,9 +15226,7 @@ extern(C++) Expression toLvalue(Expression _this, Scope* sc, Expression e) // Lvalue-ness will be handled in glue :layer. if (_this.isBinAssignExp()) return _this; - if (!e) - e = _this; - else if (!_this.loc.isValid()) + if (!_this.loc.isValid()) _this.loc = e.loc; if (e.op == EXP.type) @@ -15231,9 +15239,7 @@ extern(C++) Expression toLvalue(Expression _this, Scope* sc, Expression e) Expression visitInteger(IntegerExp _this) { - if (!e) - e = _this; - else if (!_this.loc.isValid()) + if (!_this.loc.isValid()) _this.loc = e.loc; error(e.loc, "cannot modify constant `%s`", e.toChars()); return ErrorExp.get(); @@ -15364,7 +15370,7 @@ extern(C++) Expression toLvalue(Expression _this, Scope* sc, Expression e) Expression visitVectorArray(VectorArrayExp _this) { - _this.e1 = _this.e1.toLvalue(sc, e); + _this.e1 = _this.e1.toLvalueImpl(sc, e); return _this; } @@ -15383,19 +15389,19 @@ extern(C++) Expression toLvalue(Expression _this, Scope* sc, Expression e) Expression visitComma(CommaExp _this) { - _this.e2 = _this.e2.toLvalue(sc, null); + _this.e2 = _this.e2.toLvalue(sc); return _this; } Expression visitDelegatePointer(DelegatePtrExp _this) { - _this.e1 = _this.e1.toLvalue(sc, e); + _this.e1 = _this.e1.toLvalueImpl(sc, e); return _this; } Expression visitDelegateFuncptr(DelegateFuncptrExp _this) { - _this.e1 = _this.e1.toLvalue(sc, e); + _this.e1 = _this.e1.toLvalueImpl(sc, e); return _this; } @@ -15424,8 +15430,8 @@ extern(C++) Expression toLvalue(Expression _this, Scope* sc, Expression e) { // convert (econd ? e1 : e2) to *(econd ? &e1 : &e2) CondExp e = cast(CondExp)(_this.copy()); - e.e1 = _this.e1.toLvalue(sc, null).addressOf(); - e.e2 = _this.e2.toLvalue(sc, null).addressOf(); + e.e1 = _this.e1.toLvalue(sc).addressOf(); + e.e2 = _this.e2.toLvalue(sc).addressOf(); e.type = _this.type.pointerTo(); return new PtrExp(_this.loc, e, _this.type); @@ -15620,7 +15626,7 @@ extern(C++) Expression modifiableLvalue(Expression _this, Scope* sc, Expression //printf("Expression::modifiableLvalue() %s, type = %s\n", exp.toChars(), exp.type.toChars()); // See if this expression is a modifiable lvalue (i.e. not const) if (exp.isBinAssignExp()) - return exp.toLvalue(sc, exp); + return exp.toLvalue(sc); auto type = exp.type; if (checkModifiable(exp, sc) == Modifiable.yes) @@ -15653,7 +15659,7 @@ extern(C++) Expression modifiableLvalue(Expression _this, Scope* sc, Expression return ErrorExp.get(); } } - return exp.toLvalue(sc, e); + return exp.toLvalueImpl(sc, e); } Expression visitString(StringExp exp) @@ -15743,7 +15749,7 @@ extern(C++) Expression modifiableLvalue(Expression _this, Scope* sc, Expression } exp.e1 = exp.e1.modifiableLvalue(sc, exp.e1); exp.e2 = exp.e2.modifiableLvalue(sc, exp.e2); - return exp.toLvalue(sc, exp); + return exp.toLvalue(sc); } switch(_this.op) diff --git a/dmd/frontend.h b/dmd/frontend.h index d40051b0800..74414f30944 100644 --- a/dmd/frontend.h +++ b/dmd/frontend.h @@ -7989,7 +7989,7 @@ extern Expression* resolveProperties(Scope* sc, Expression* e); extern Expression* expressionSemantic(Expression* e, Scope* sc); -extern Expression* toLvalue(Expression* _this, Scope* sc, Expression* e); +extern Expression* toLvalue(Expression* _this, Scope* sc); extern Expression* modifiableLvalue(Expression* _this, Scope* sc, Expression* e); diff --git a/dmd/inline.d b/dmd/inline.d index 9ac3a1644d9..0d58eb3b657 100644 --- a/dmd/inline.d +++ b/dmd/inline.d @@ -2190,7 +2190,7 @@ private void expandInline(Loc callLoc, FuncDeclaration fd, FuncDeclaration paren import dmd.expressionsem : toLvalue; // https://issues.dlang.org/show_bug.cgi?id=11322 if (tf.isref) - e = e.toLvalue(null, null); + e = e.toLvalue(null); /* If the inlined function returns a copy of a struct, * and then the return value is used subsequently as an diff --git a/dmd/semantic3.d b/dmd/semantic3.d index 8af79bfc2d5..bf220f31d9b 100644 --- a/dmd/semantic3.d +++ b/dmd/semantic3.d @@ -918,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); } diff --git a/dmd/typesem.d b/dmd/typesem.d index bc0ae18eaad..413d01f67cd 100644 --- a/dmd/typesem.d +++ b/dmd/typesem.d @@ -1157,7 +1157,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); From e650bcf8d5fab1ff45fd82418a8a53db95c2120c Mon Sep 17 00:00:00 2001 From: Iain Buclaw Date: Sun, 12 Nov 2023 14:45:25 +0100 Subject: [PATCH 019/215] Revert "Move a couple of functions out of dsymbol.d (dlang/dmd!15789)" This reverts commit c698cccf94cc11576fcb5fa24acaa420a86ab1dd. --- dmd/dsymbol.d | 91 ++++++++++++++++++++++++++++++++++++++++++++++++++ dmd/dsymbol.h | 1 + dmd/frontend.h | 3 +- dmd/typesem.d | 58 -------------------------------- dmd/typinf.d | 36 -------------------- dmd/typinf.h | 3 -- 6 files changed, 93 insertions(+), 99 deletions(-) diff --git a/dmd/dsymbol.d b/dmd/dsymbol.d index a662e5a12a6..914213c1e57 100644 --- a/dmd/dsymbol.d +++ b/dmd/dsymbol.d @@ -45,6 +45,7 @@ import dmd.lexer; import dmd.location; import dmd.mtype; import dmd.nspace; +import dmd.opover; import dmd.root.aav; import dmd.root.rmem; import dmd.rootobject; @@ -874,6 +875,64 @@ extern (C++) class Dsymbol : ASTNode return speller!symbol_search_fp(ident.toString()); } + /*************************************** + * Search for identifier id as a member of `this`. + * `id` may be a template instance. + * + * Params: + * loc = location to print the error messages + * sc = the scope where the symbol is located + * id = the id of the symbol + * flags = the search flags which can be `SearchLocalsOnly` or `IgnorePrivateImports` + * + * Returns: + * symbol found, NULL if not + */ + extern (D) final Dsymbol searchX(const ref Loc loc, Scope* sc, RootObject id, int flags) + { + //printf("Dsymbol::searchX(this=%p,%s, ident='%s')\n", this, toChars(), ident.toChars()); + Dsymbol s = toAlias(); + Dsymbol sm; + if (Declaration d = s.isDeclaration()) + { + if (d.inuse) + { + .error(loc, "circular reference to `%s`", d.toPrettyChars()); + return null; + } + } + switch (id.dyncast()) + { + case DYNCAST.identifier: + sm = s.search(loc, cast(Identifier)id, flags); + break; + case DYNCAST.dsymbol: + { + // It's a template instance + //printf("\ttemplate instance id\n"); + Dsymbol st = cast(Dsymbol)id; + TemplateInstance ti = st.isTemplateInstance(); + sm = s.search(loc, ti.name); + if (!sm) + return null; + sm = sm.toAlias(); + TemplateDeclaration td = sm.isTemplateDeclaration(); + if (!td) + return null; // error but handled later + ti.tempdecl = td; + if (!ti.semanticRun) + ti.dsymbolSemantic(sc); + sm = ti.toAlias(); + break; + } + case DYNCAST.type: + case DYNCAST.expression: + default: + assert(0); + } + return sm; + } + bool overloadInsert(Dsymbol s) { //printf("Dsymbol::overloadInsert('%s')\n", s.toChars()); @@ -1645,6 +1704,38 @@ public: return "ScopeDsymbol"; } + /******************************************* + * Look for member of the form: + * const(MemberInfo)[] getMembers(string); + * Returns NULL if not found + */ + final FuncDeclaration findGetMembers() + { + Dsymbol s = search_function(this, Id.getmembers); + FuncDeclaration fdx = s ? s.isFuncDeclaration() : null; + version (none) + { + // Finish + __gshared TypeFunction tfgetmembers; + if (!tfgetmembers) + { + Scope sc; + sc.eSink = global.errorSink; + auto parameters = new Parameters(); + Parameters* p = new Parameter(STC.in_, Type.tchar.constOf().arrayOf(), null, null); + parameters.push(p); + Type tret = null; + TypeFunction tf = new TypeFunction(parameters, tret, VarArg.none, LINK.d); + tfgetmembers = tf.dsymbolSemantic(Loc.initial, &sc).isTypeFunction(); + } + if (fdx) + fdx = fdx.overloadExactMatch(tfgetmembers); + } + if (fdx && fdx.isVirtual()) + fdx = null; + return fdx; + } + /******************************** * Insert Dsymbol in table. * Params: diff --git a/dmd/dsymbol.h b/dmd/dsymbol.h index 243b0d78419..027897532d1 100644 --- a/dmd/dsymbol.h +++ b/dmd/dsymbol.h @@ -346,6 +346,7 @@ class ScopeDsymbol : public Dsymbol bool isforwardRef() override final; static void multiplyDefined(const Loc &loc, Dsymbol *s1, Dsymbol *s2); const char *kind() const override; + FuncDeclaration *findGetMembers(); virtual Dsymbol *symtabInsert(Dsymbol *s); virtual Dsymbol *symtabLookup(Dsymbol *s, Identifier *id); bool hasStaticCtorOrDtor() override; diff --git a/dmd/frontend.h b/dmd/frontend.h index 74414f30944..c488de948eb 100644 --- a/dmd/frontend.h +++ b/dmd/frontend.h @@ -632,6 +632,7 @@ class ScopeDsymbol : public Dsymbol bool isforwardRef() final override; static void multiplyDefined(const Loc& loc, Dsymbol* s1, Dsymbol* s2); const char* kind() const override; + FuncDeclaration* findGetMembers(); virtual Dsymbol* symtabInsert(Dsymbol* s); virtual Dsymbol* symtabLookup(Dsymbol* s, Identifier* id); bool hasStaticCtorOrDtor() override; @@ -8228,8 +8229,6 @@ extern bool isSpeculativeType(Type* t); extern bool builtinTypeInfo(Type* t); -extern FuncDeclaration* findGetMembers(ScopeDsymbol* dsym); - class SemanticTimeTransitiveVisitor : public SemanticTimePermissiveVisitor { public: diff --git a/dmd/typesem.d b/dmd/typesem.d index 413d01f67cd..4a4c5d4f7f0 100644 --- a/dmd/typesem.d +++ b/dmd/typesem.d @@ -372,64 +372,6 @@ private void resolveHelper(TypeQualified mt, const ref Loc loc, Scope* sc, Dsymb pt = t.merge(); } -/*************************************** - * Search for identifier id as a member of `this`. - * `id` may be a template instance. - * - * Params: - * loc = location to print the error messages - * sc = the scope where the symbol is located - * id = the id of the symbol - * flags = the search flags which can be `SearchLocalsOnly` or `IgnorePrivateImports` - * - * Returns: - * symbol found, NULL if not - */ -private Dsymbol searchX(Dsymbol dsym, const ref Loc loc, Scope* sc, RootObject id, int flags) -{ - //printf("Dsymbol::searchX(this=%p,%s, ident='%s')\n", this, toChars(), ident.toChars()); - Dsymbol s = dsym.toAlias(); - Dsymbol sm; - if (Declaration d = s.isDeclaration()) - { - if (d.inuse) - { - .error(loc, "circular reference to `%s`", d.toPrettyChars()); - return null; - } - } - switch (id.dyncast()) - { - case DYNCAST.identifier: - sm = s.search(loc, cast(Identifier)id, flags); - break; - case DYNCAST.dsymbol: - { - // It's a template instance - //printf("\ttemplate instance id\n"); - Dsymbol st = cast(Dsymbol)id; - TemplateInstance ti = st.isTemplateInstance(); - sm = s.search(loc, ti.name); - if (!sm) - return null; - sm = sm.toAlias(); - TemplateDeclaration td = sm.isTemplateDeclaration(); - if (!td) - return null; // error but handled later - ti.tempdecl = td; - if (!ti.semanticRun) - ti.dsymbolSemantic(sc); - sm = ti.toAlias(); - break; - } - case DYNCAST.type: - case DYNCAST.expression: - default: - assert(0); - } - return sm; -} - /****************************************** * We've mistakenly parsed `t` as a type. * Redo `t` as an Expression only if there are no type modifiers. diff --git a/dmd/typinf.d b/dmd/typinf.d index 0d0ae35df91..5890fa1b61d 100644 --- a/dmd/typinf.d +++ b/dmd/typinf.d @@ -15,17 +15,13 @@ import dmd.astenums; import dmd.declaration; import dmd.dmodule; import dmd.dscope; -import dmd.dsymbol; import dmd.dclass; import dmd.dstruct; import dmd.errors; import dmd.expression; -import dmd.func; import dmd.globals; -import dmd.id; import dmd.location; import dmd.mtype; -import dmd.opover; import core.stdc.stdio; /**************************************************** @@ -275,35 +271,3 @@ extern (C++) bool builtinTypeInfo(Type t) } return false; } - -/******************************************* - * Look for member of the form: - * const(MemberInfo)[] getMembers(string); - * Returns NULL if not found - */ -extern(C++) FuncDeclaration findGetMembers(ScopeDsymbol dsym) -{ - Dsymbol s = search_function(dsym, Id.getmembers); - FuncDeclaration fdx = s ? s.isFuncDeclaration() : null; - version (none) - { - // Finish - __gshared TypeFunction tfgetmembers; - if (!tfgetmembers) - { - Scope sc; - sc.eSink = global.errorSink; - auto parameters = new Parameters(); - Parameters* p = new Parameter(STC.in_, Type.tchar.constOf().arrayOf(), null, null); - parameters.push(p); - Type tret = null; - TypeFunction tf = new TypeFunction(parameters, tret, VarArg.none, LINK.d); - tfgetmembers = tf.dsymbolSemantic(Loc.initial, &sc).isTypeFunction(); - } - if (fdx) - fdx = fdx.overloadExactMatch(tfgetmembers); - } - if (fdx && fdx.isVirtual()) - fdx = null; - return fdx; -} diff --git a/dmd/typinf.h b/dmd/typinf.h index b5c144fa8ee..76f623a0a3e 100644 --- a/dmd/typinf.h +++ b/dmd/typinf.h @@ -15,11 +15,8 @@ class Expression; class Type; struct Scope; -class FuncDeclaration; -class ScopeDsymbol; bool genTypeInfo(Expression *e, const Loc &loc, Type *torig, Scope *sc); Type *getTypeInfoType(const Loc &loc, Type *t, Scope *sc, bool genObjCode = true); bool isSpeculativeType(Type *t); bool builtinTypeInfo(Type *t); -FuncDeclaration *findGetMembers(ScopeDsymbol *dsym); From b58122e26f861fa6723c6148a4df2ec53a4d771d Mon Sep 17 00:00:00 2001 From: ryuukk <44361234+ryuukk@users.noreply.github.com> Date: Sun, 12 Nov 2023 16:53:42 +0100 Subject: [PATCH 020/215] Local import should be explicit --- dmd/dsymbolsem.d | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dmd/dsymbolsem.d b/dmd/dsymbolsem.d index 637edd7bf08..d9515fe6b23 100644 --- a/dmd/dsymbolsem.d +++ b/dmd/dsymbolsem.d @@ -3385,7 +3385,7 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor if (!tf.isNaked() && !(funcdecl.isThis() || funcdecl.isNested())) { - import core.bitop; + import core.bitop : popcnt; 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) From 26b9de5cb6160d6b9a6ac484efc7a9a51b546565 Mon Sep 17 00:00:00 2001 From: Dennis Korpel Date: Fri, 10 Nov 2023 15:43:59 +0100 Subject: [PATCH 021/215] Fix 24238 - Confusing "not an lvalue"error messages --- dmd/expression.h | 2 +- dmd/expressionsem.d | 55 ++++++++++++---------- dmd/frontend.h | 2 +- dmd/inline.d | 2 +- dmd/semantic3.d | 2 +- dmd/typesem.d | 2 +- tests/dmd/fail_compilation/b20011.d | 8 ++-- tests/dmd/fail_compilation/diag10862.d | 4 +- tests/dmd/fail_compilation/diag10926.d | 2 +- tests/dmd/fail_compilation/diag14102.d | 8 ++-- tests/dmd/fail_compilation/diag4596.d | 4 +- tests/dmd/fail_compilation/fail10299.d | 2 +- tests/dmd/fail_compilation/fail13116.d | 4 +- tests/dmd/fail_compilation/fail13336a.d | 2 +- tests/dmd/fail_compilation/fail13336b.d | 4 +- tests/dmd/fail_compilation/fail17491.d | 16 +++---- tests/dmd/fail_compilation/fail6795.d | 12 ++--- tests/dmd/fail_compilation/fail7603a.d | 2 +- tests/dmd/fail_compilation/fail7603b.d | 2 +- tests/dmd/fail_compilation/fail7603c.d | 2 +- tests/dmd/fail_compilation/fail9537.d | 2 +- tests/dmd/fail_compilation/fail9773.d | 2 +- tests/dmd/fail_compilation/fail9891.d | 2 +- tests/dmd/fail_compilation/fail_arrayop2.d | 12 ++--- tests/dmd/fail_compilation/failcstuff2.c | 28 +++++------ tests/dmd/fail_compilation/ice10419.d | 2 +- tests/dmd/fail_compilation/ice12841.d | 4 +- tests/dmd/fail_compilation/ice20264.d | 2 +- tests/dmd/fail_compilation/issue20704.d | 8 ++-- tests/dmd/fail_compilation/test16381.d | 2 +- tests/dmd/fail_compilation/test22070.c | 2 +- tests/dmd/fail_compilation/test24157.d | 4 +- tests/dmd/fail_compilation/tolvalue.d | 48 +++++++++++++++++++ 33 files changed, 155 insertions(+), 100 deletions(-) create mode 100644 tests/dmd/fail_compilation/tolvalue.d diff --git a/dmd/expression.h b/dmd/expression.h index 86675d5df39..833db0403ee 100644 --- a/dmd/expression.h +++ b/dmd/expression.h @@ -52,7 +52,7 @@ 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 *toLvalue(Expression *_this, Scope *sc, const char* action); Expression *modifiableLvalue(Expression* exp, Scope *sc, Expression *e); typedef unsigned char OwnedBy; diff --git a/dmd/expressionsem.d b/dmd/expressionsem.d index abdaf189919..22b3fdaed2f 100644 --- a/dmd/expressionsem.d +++ b/dmd/expressionsem.d @@ -3129,7 +3129,7 @@ private bool functionParameters(const ref Loc loc, Scope* sc, ev = new CommaExp(arg.loc, ev, new VarExp(arg.loc, v)); arg = ev.expressionSemantic(sc); } - arg = arg.toLvalue(sc); + arg = arg.toLvalue(sc, "create `in` parameter from"); // Look for mutable misaligned pointer, etc., in @safe mode err |= checkUnsafeAccess(sc, arg, false, true); @@ -3147,7 +3147,7 @@ private bool functionParameters(const ref Loc loc, Scope* sc, ev = new CommaExp(arg.loc, ev, new VarExp(arg.loc, v)); arg = ev.expressionSemantic(sc); } - arg = arg.toLvalue(sc); + arg = arg.toLvalue(sc, "create `ref` parameter from"); // Look for mutable misaligned pointer, etc., in @safe mode err |= checkUnsafeAccess(sc, arg, false, true); @@ -3166,7 +3166,7 @@ private bool functionParameters(const ref Loc loc, Scope* sc, err |= checkUnsafeAccess(sc, arg, false, true); err |= checkDefCtor(arg.loc, t); // t must be default constructible } - arg = arg.toLvalue(sc); + arg = arg.toLvalue(sc, "create `out` parameter from"); } else if (p.isLazy()) { @@ -8295,7 +8295,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor else { // `toLvalue` call further below is upon exp.e1, omitting & from the error message - exp.toLvalue(sc); + exp.toLvalue(sc, "take address of"); return setError(); } } @@ -8385,7 +8385,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor } } - exp.e1 = exp.e1.toLvalue(sc); + exp.e1 = exp.e1.toLvalue(sc, "take address of"); if (exp.e1.op == EXP.error) { result = exp.e1; @@ -15210,15 +15210,20 @@ Expression addDtorHook(Expression e, Scope* sc) * Params: * _this = expression to convert * sc = scope + * action = for error messages, what the lvalue is needed for (e.g. take address of for `&x`, modify for `x++`) * Returns: converted expression, or `ErrorExp` on error */ -extern(C++) Expression toLvalue(Expression _this, Scope* sc) +extern(C++) Expression toLvalue(Expression _this, Scope* sc, const(char)* action) { - return toLvalueImpl(_this, sc, _this); + return toLvalueImpl(_this, sc, action, _this); } // e = original un-lowered expression for error messages, in case of recursive calls -private Expression toLvalueImpl(Expression _this, Scope* sc, Expression e) { +private Expression toLvalueImpl(Expression _this, Scope* sc, const(char)* action, Expression e) +{ + if (!action) + action = "create lvalue of"; + Expression visit(Expression _this) { // BinaryAssignExp does not have an EXP associated @@ -15230,9 +15235,11 @@ private Expression toLvalueImpl(Expression _this, Scope* sc, Expression e) { _this.loc = e.loc; if (e.op == EXP.type) - error(_this.loc, "`%s` is a `%s` definition and cannot be modified", e.type.toChars(), e.type.kind()); + error(_this.loc, "cannot %s type `%s`", action, e.type.toChars()); + else if (e.op == EXP.template_) + error(_this.loc, "cannot %s template `%s`, perhaps instantiate it first", action, e.toChars()); else - error(_this.loc, "`%s` is not an lvalue and cannot be modified", e.toChars()); + error(_this.loc, "cannot %s expression `%s` because it is not an lvalue", action, e.toChars()); return ErrorExp.get(); } @@ -15241,7 +15248,7 @@ private Expression toLvalueImpl(Expression _this, Scope* sc, Expression e) { { if (!_this.loc.isValid()) _this.loc = e.loc; - error(e.loc, "cannot modify constant `%s`", e.toChars()); + error(e.loc, "cannot %s constant `%s`", action, e.toChars()); return ErrorExp.get(); } @@ -15285,22 +15292,22 @@ private Expression toLvalueImpl(Expression _this, Scope* sc, Expression e) { auto var = _this.var; if (var.storage_class & STC.manifest) { - error(_this.loc, "manifest constant `%s` cannot be modified", var.toChars()); + error(_this.loc, "cannot %s manifest constant `%s`", action, var.toChars()); return ErrorExp.get(); } if (var.storage_class & STC.lazy_ && !_this.delegateWasExtracted) { - error(_this.loc, "lazy variable `%s` cannot be modified", var.toChars()); + error(_this.loc, "cannot %s lazy variable `%s`", action, var.toChars()); return ErrorExp.get(); } if (var.ident == Id.ctfe) { - error(_this.loc, "cannot modify compiler-generated variable `__ctfe`"); + error(_this.loc, "cannot %s compiler-generated variable `__ctfe`", action); return ErrorExp.get(); } if (var.ident == Id.dollar) // https://issues.dlang.org/show_bug.cgi?id=13574 { - error(_this.loc, "cannot modify operator `$`"); + error(_this.loc, "cannot %s operator `$`", action); return ErrorExp.get(); } return _this; @@ -15370,7 +15377,7 @@ private Expression toLvalueImpl(Expression _this, Scope* sc, Expression e) { Expression visitVectorArray(VectorArrayExp _this) { - _this.e1 = _this.e1.toLvalueImpl(sc, e); + _this.e1 = _this.e1.toLvalueImpl(sc, action, e); return _this; } @@ -15389,19 +15396,19 @@ private Expression toLvalueImpl(Expression _this, Scope* sc, Expression e) { Expression visitComma(CommaExp _this) { - _this.e2 = _this.e2.toLvalue(sc); + _this.e2 = _this.e2.toLvalue(sc, action); return _this; } Expression visitDelegatePointer(DelegatePtrExp _this) { - _this.e1 = _this.e1.toLvalueImpl(sc, e); + _this.e1 = _this.e1.toLvalueImpl(sc, action, e); return _this; } Expression visitDelegateFuncptr(DelegateFuncptrExp _this) { - _this.e1 = _this.e1.toLvalueImpl(sc, e); + _this.e1 = _this.e1.toLvalueImpl(sc, action, e); return _this; } @@ -15430,8 +15437,8 @@ private Expression toLvalueImpl(Expression _this, Scope* sc, Expression e) { { // convert (econd ? e1 : e2) to *(econd ? &e1 : &e2) CondExp e = cast(CondExp)(_this.copy()); - e.e1 = _this.e1.toLvalue(sc).addressOf(); - e.e2 = _this.e2.toLvalue(sc).addressOf(); + e.e1 = _this.e1.toLvalue(sc, action).addressOf(); + e.e2 = _this.e2.toLvalue(sc, action).addressOf(); e.type = _this.type.pointerTo(); return new PtrExp(_this.loc, e, _this.type); @@ -15626,7 +15633,7 @@ extern(C++) Expression modifiableLvalue(Expression _this, Scope* sc, Expression //printf("Expression::modifiableLvalue() %s, type = %s\n", exp.toChars(), exp.type.toChars()); // See if this expression is a modifiable lvalue (i.e. not const) if (exp.isBinAssignExp()) - return exp.toLvalue(sc); + return exp.toLvalue(sc, "modify"); auto type = exp.type; if (checkModifiable(exp, sc) == Modifiable.yes) @@ -15659,7 +15666,7 @@ extern(C++) Expression modifiableLvalue(Expression _this, Scope* sc, Expression return ErrorExp.get(); } } - return exp.toLvalueImpl(sc, e); + return exp.toLvalueImpl(sc, "modify", e); } Expression visitString(StringExp exp) @@ -15749,7 +15756,7 @@ extern(C++) Expression modifiableLvalue(Expression _this, Scope* sc, Expression } exp.e1 = exp.e1.modifiableLvalue(sc, exp.e1); exp.e2 = exp.e2.modifiableLvalue(sc, exp.e2); - return exp.toLvalue(sc); + return exp.toLvalue(sc, "modify"); } switch(_this.op) diff --git a/dmd/frontend.h b/dmd/frontend.h index 74414f30944..40265d07db2 100644 --- a/dmd/frontend.h +++ b/dmd/frontend.h @@ -7989,7 +7989,7 @@ extern Expression* resolveProperties(Scope* sc, Expression* e); extern Expression* expressionSemantic(Expression* e, Scope* sc); -extern Expression* toLvalue(Expression* _this, Scope* sc); +extern Expression* toLvalue(Expression* _this, Scope* sc, const char* action); extern Expression* modifiableLvalue(Expression* _this, Scope* sc, Expression* e); diff --git a/dmd/inline.d b/dmd/inline.d index 0d58eb3b657..77093f0faf6 100644 --- a/dmd/inline.d +++ b/dmd/inline.d @@ -2190,7 +2190,7 @@ private void expandInline(Loc callLoc, FuncDeclaration fd, FuncDeclaration paren import dmd.expressionsem : toLvalue; // https://issues.dlang.org/show_bug.cgi?id=11322 if (tf.isref) - e = e.toLvalue(null); + e = e.toLvalue(null, "`ref` return"); /* If the inlined function returns a copy of a struct, * and then the return value is used subsequently as an diff --git a/dmd/semantic3.d b/dmd/semantic3.d index bf220f31d9b..c255701d767 100644 --- a/dmd/semantic3.d +++ b/dmd/semantic3.d @@ -918,7 +918,7 @@ private extern(C++) final class Semantic3Visitor : Visitor if (f.isref) { // Function returns a reference - exp = exp.toLvalue(sc2); + exp = exp.toLvalue(sc2, "`ref` return"); checkReturnEscapeRef(sc2, exp, false); exp = exp.optimize(WANTvalue, /*keepLvalue*/ true); } diff --git a/dmd/typesem.d b/dmd/typesem.d index 413d01f67cd..2063a954b99 100644 --- a/dmd/typesem.d +++ b/dmd/typesem.d @@ -1157,7 +1157,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.toLvalue(sc, "create default argument for `ref` / `out` parameter from"); fparam.defaultArg = e; return (e.op != EXP.error); diff --git a/tests/dmd/fail_compilation/b20011.d b/tests/dmd/fail_compilation/b20011.d index 7baad47f378..3ddcdaaf76b 100644 --- a/tests/dmd/fail_compilation/b20011.d +++ b/tests/dmd/fail_compilation/b20011.d @@ -1,10 +1,10 @@ /* TEST_OUTPUT: --- -fail_compilation/b20011.d(25): Error: `S1(cast(ubyte)0u).member` is not an lvalue and cannot be modified -fail_compilation/b20011.d(28): Error: `S2(null).member` is not an lvalue and cannot be modified -fail_compilation/b20011.d(29): Error: `S2(null).member` is not an lvalue and cannot be modified -fail_compilation/b20011.d(32): Error: `U1(cast(ubyte)0u, ).m2` is not an lvalue and cannot be modified +fail_compilation/b20011.d(25): Error: cannot modify expression `S1(cast(ubyte)0u).member` because it is not an lvalue +fail_compilation/b20011.d(28): Error: cannot modify expression `S2(null).member` because it is not an lvalue +fail_compilation/b20011.d(29): Error: cannot modify expression `S2(null).member` because it is not an lvalue +fail_compilation/b20011.d(32): Error: cannot modify expression `U1(cast(ubyte)0u, ).m2` because it is not an lvalue fail_compilation/b20011.d(37): Error: function `b20011.main.assignableByRef(ref ubyte p)` is not callable using argument types `(ubyte)` fail_compilation/b20011.d(37): cannot pass rvalue argument `S1(cast(ubyte)0u).member` of type `ubyte` to parameter `ref ubyte p` fail_compilation/b20011.d(38): Error: function `b20011.main.assignableByOut(out ubyte p)` is not callable using argument types `(ubyte)` diff --git a/tests/dmd/fail_compilation/diag10862.d b/tests/dmd/fail_compilation/diag10862.d index 3e154979e8c..2c9384159ff 100644 --- a/tests/dmd/fail_compilation/diag10862.d +++ b/tests/dmd/fail_compilation/diag10862.d @@ -26,10 +26,10 @@ fail_compilation/diag10862.d-mixin-78(78): Error: assignment cannot be used as a fail_compilation/diag10862.d-mixin-79(79): Error: assignment cannot be used as a condition, perhaps `==` was meant? fail_compilation/diag10862.d-mixin-80(80): Error: using the result of a comma expression is not allowed fail_compilation/diag10862.d-mixin-80(80): Error: assignment cannot be used as a condition, perhaps `==` was meant? -fail_compilation/diag10862.d-mixin-83(83): Error: `a + b` is not an lvalue and cannot be modified +fail_compilation/diag10862.d-mixin-83(83): Error: cannot modify expression `a + b` because it is not an lvalue fail_compilation/diag10862.d-mixin-84(84): Error: undefined identifier `c` fail_compilation/diag10862.d(86): Error: undefined identifier `semanticError` -fail_compilation/diag10862.d(93): Error: lazy variable `bar` cannot be modified +fail_compilation/diag10862.d(93): Error: cannot modify lazy variable `bar` fail_compilation/diag10862.d(95): Error: template instance `diag10862.test3.foo!int` error instantiating --- */ diff --git a/tests/dmd/fail_compilation/diag10926.d b/tests/dmd/fail_compilation/diag10926.d index f98a5b27dea..9bad6336d18 100644 --- a/tests/dmd/fail_compilation/diag10926.d +++ b/tests/dmd/fail_compilation/diag10926.d @@ -1,7 +1,7 @@ /* TEST_OUTPUT: --- -fail_compilation/diag10926.d(11): Error: `cast(const(int)[])c` is not an lvalue and cannot be modified +fail_compilation/diag10926.d(11): Error: cannot modify expression `cast(const(int)[])c` because it is not an lvalue --- */ diff --git a/tests/dmd/fail_compilation/diag14102.d b/tests/dmd/fail_compilation/diag14102.d index e93d40b224e..b88dd7803cf 100644 --- a/tests/dmd/fail_compilation/diag14102.d +++ b/tests/dmd/fail_compilation/diag14102.d @@ -1,10 +1,10 @@ /* TEST_OUTPUT: --- -fail_compilation/diag14102.d(14): Error: `-x` is not an lvalue and cannot be modified -fail_compilation/diag14102.d(15): Error: `-(x -= 1)` is not an lvalue and cannot be modified -fail_compilation/diag14102.d(16): Error: `-(x -= 1 -= 1)` is not an lvalue and cannot be modified -fail_compilation/diag14102.d(17): Error: `-(x -= 1 -= 1 -= 1)` is not an lvalue and cannot be modified +fail_compilation/diag14102.d(14): Error: cannot modify expression `-x` because it is not an lvalue +fail_compilation/diag14102.d(15): Error: cannot modify expression `-(x -= 1)` because it is not an lvalue +fail_compilation/diag14102.d(16): Error: cannot modify expression `-(x -= 1 -= 1)` because it is not an lvalue +fail_compilation/diag14102.d(17): Error: cannot modify expression `-(x -= 1 -= 1 -= 1)` because it is not an lvalue --- */ diff --git a/tests/dmd/fail_compilation/diag4596.d b/tests/dmd/fail_compilation/diag4596.d index f6b49d6bd13..d43342bdc58 100644 --- a/tests/dmd/fail_compilation/diag4596.d +++ b/tests/dmd/fail_compilation/diag4596.d @@ -1,9 +1,9 @@ /* TEST_OUTPUT: --- -fail_compilation/diag4596.d(15): Error: `this` is not an lvalue and cannot be modified +fail_compilation/diag4596.d(15): Error: cannot modify expression `this` because it is not an lvalue fail_compilation/diag4596.d(16): Error: conditional expression `1 ? this : this` is not a modifiable lvalue -fail_compilation/diag4596.d(18): Error: `super` is not an lvalue and cannot be modified +fail_compilation/diag4596.d(18): Error: cannot modify expression `super` because it is not an lvalue fail_compilation/diag4596.d(19): Error: conditional expression `1 ? super : super` is not a modifiable lvalue --- */ diff --git a/tests/dmd/fail_compilation/fail10299.d b/tests/dmd/fail_compilation/fail10299.d index f0eaeba821a..d9cfb047724 100644 --- a/tests/dmd/fail_compilation/fail10299.d +++ b/tests/dmd/fail_compilation/fail10299.d @@ -1,7 +1,7 @@ /* TEST_OUTPUT: --- -fail_compilation/fail10299.d(11): Error: `foo!string` is not an lvalue and cannot be modified +fail_compilation/fail10299.d(11): Error: cannot take address of expression `foo!string` because it is not an lvalue --- */ diff --git a/tests/dmd/fail_compilation/fail13116.d b/tests/dmd/fail_compilation/fail13116.d index ac520d79997..156da435c7b 100644 --- a/tests/dmd/fail_compilation/fail13116.d +++ b/tests/dmd/fail_compilation/fail13116.d @@ -1,8 +1,8 @@ /* TEST_OUTPUT: --- -fail_compilation/fail13116.d(14): Error: `this` is not an lvalue and cannot be modified -fail_compilation/fail13116.d(23): Error: `super` is not an lvalue and cannot be modified +fail_compilation/fail13116.d(14): Error: cannot `ref` return expression `this` because it is not an lvalue +fail_compilation/fail13116.d(23): Error: cannot `ref` return expression `super` because it is not an lvalue --- */ struct S diff --git a/tests/dmd/fail_compilation/fail13336a.d b/tests/dmd/fail_compilation/fail13336a.d index e3f990c2fdf..6307e902551 100644 --- a/tests/dmd/fail_compilation/fail13336a.d +++ b/tests/dmd/fail_compilation/fail13336a.d @@ -1,7 +1,7 @@ /* TEST_OUTPUT: --- -fail_compilation/fail13336a.d(28): Error: `choose(true)` is not an lvalue and cannot be modified +fail_compilation/fail13336a.d(28): Error: cannot modify expression `choose(true)` because it is not an lvalue --- */ diff --git a/tests/dmd/fail_compilation/fail13336b.d b/tests/dmd/fail_compilation/fail13336b.d index b8fb12d1427..f8959a2183c 100644 --- a/tests/dmd/fail_compilation/fail13336b.d +++ b/tests/dmd/fail_compilation/fail13336b.d @@ -6,8 +6,8 @@ double sy; /* TEST_OUTPUT: --- -fail_compilation/fail13336b.d(16): Error: `cast(double)sx` is not an lvalue and cannot be modified -fail_compilation/fail13336b.d(24): Error: `cast(double)sx` is not an lvalue and cannot be modified +fail_compilation/fail13336b.d(16): Error: cannot `ref` return expression `cast(double)sx` because it is not an lvalue +fail_compilation/fail13336b.d(24): Error: cannot `ref` return expression `cast(double)sx` because it is not an lvalue --- */ ref f1(bool f) diff --git a/tests/dmd/fail_compilation/fail17491.d b/tests/dmd/fail_compilation/fail17491.d index 0fb9708b430..718948c2832 100644 --- a/tests/dmd/fail_compilation/fail17491.d +++ b/tests/dmd/fail_compilation/fail17491.d @@ -1,13 +1,13 @@ /* TEST_OUTPUT: --- -fail_compilation/fail17491.d(22): Error: `(S17491).init` is not an lvalue and cannot be modified -fail_compilation/fail17491.d(23): Error: `S17491(0)` is not an lvalue and cannot be modified -fail_compilation/fail17491.d(25): Error: `S17491(0).field` is not an lvalue and cannot be modified -fail_compilation/fail17491.d(26): Error: `S17491(0).field` is not an lvalue and cannot be modified -fail_compilation/fail17491.d(31): Error: `S17491(0)` is not an lvalue and cannot be modified -fail_compilation/fail17491.d(32): Error: `S17491(0)` is not an lvalue and cannot be modified -fail_compilation/fail17491.d(34): Error: `S17491(0).field` is not an lvalue and cannot be modified -fail_compilation/fail17491.d(35): Error: `S17491(0).field` is not an lvalue and cannot be modified +fail_compilation/fail17491.d(22): Error: cannot modify expression `(S17491).init` because it is not an lvalue +fail_compilation/fail17491.d(23): Error: cannot take address of expression `S17491(0)` because it is not an lvalue +fail_compilation/fail17491.d(25): Error: cannot modify expression `S17491(0).field` because it is not an lvalue +fail_compilation/fail17491.d(26): Error: cannot take address of expression `S17491(0).field` because it is not an lvalue +fail_compilation/fail17491.d(31): Error: cannot modify expression `S17491(0)` because it is not an lvalue +fail_compilation/fail17491.d(32): Error: cannot take address of expression `S17491(0)` because it is not an lvalue +fail_compilation/fail17491.d(34): Error: cannot modify expression `S17491(0).field` because it is not an lvalue +fail_compilation/fail17491.d(35): Error: cannot take address of expression `S17491(0).field` because it is not an lvalue --- */ // https://issues.dlang.org/show_bug.cgi?id=17491 diff --git a/tests/dmd/fail_compilation/fail6795.d b/tests/dmd/fail_compilation/fail6795.d index 584a4679ccd..26d44296498 100644 --- a/tests/dmd/fail_compilation/fail6795.d +++ b/tests/dmd/fail_compilation/fail6795.d @@ -2,12 +2,12 @@ /* TEST_OUTPUT: --- -fail_compilation/fail6795.d(19): Error: `[0][0]` is not an lvalue and cannot be modified -fail_compilation/fail6795.d(20): Error: `[0:0][0]` is not an lvalue and cannot be modified -fail_compilation/fail6795.d(22): Error: `[0][0]` is not an lvalue and cannot be modified -fail_compilation/fail6795.d(23): Error: `[0:0][0]` is not an lvalue and cannot be modified -fail_compilation/fail6795.d(25): Error: `[0][0]` is not an lvalue and cannot be modified -fail_compilation/fail6795.d(26): Error: `[0:0][0]` is not an lvalue and cannot be modified +fail_compilation/fail6795.d(19): Error: cannot modify expression `[0][0]` because it is not an lvalue +fail_compilation/fail6795.d(20): Error: cannot modify expression `[0:0][0]` because it is not an lvalue +fail_compilation/fail6795.d(22): Error: cannot modify expression `[0][0]` because it is not an lvalue +fail_compilation/fail6795.d(23): Error: cannot modify expression `[0:0][0]` because it is not an lvalue +fail_compilation/fail6795.d(25): Error: cannot take address of expression `[0][0]` because it is not an lvalue +fail_compilation/fail6795.d(26): Error: cannot take address of expression `[0:0][0]` because it is not an lvalue --- */ diff --git a/tests/dmd/fail_compilation/fail7603a.d b/tests/dmd/fail_compilation/fail7603a.d index 76a92c2b193..a106a566a5c 100644 --- a/tests/dmd/fail_compilation/fail7603a.d +++ b/tests/dmd/fail_compilation/fail7603a.d @@ -1,7 +1,7 @@ /* TEST_OUTPUT: --- -fail_compilation/fail7603a.d(7): Error: cannot modify constant `true` +fail_compilation/fail7603a.d(7): Error: cannot create default argument for `ref` / `out` parameter from constant `true` --- */ void test(ref bool val = true) { } diff --git a/tests/dmd/fail_compilation/fail7603b.d b/tests/dmd/fail_compilation/fail7603b.d index 9b84d3f6a4d..a6524221afd 100644 --- a/tests/dmd/fail_compilation/fail7603b.d +++ b/tests/dmd/fail_compilation/fail7603b.d @@ -1,7 +1,7 @@ /* TEST_OUTPUT: --- -fail_compilation/fail7603b.d(7): Error: cannot modify constant `true` +fail_compilation/fail7603b.d(7): Error: cannot create default argument for `ref` / `out` parameter from constant `true` --- */ void test(out bool val = true) { } diff --git a/tests/dmd/fail_compilation/fail7603c.d b/tests/dmd/fail_compilation/fail7603c.d index 25a7399dd7a..3d030fc9668 100644 --- a/tests/dmd/fail_compilation/fail7603c.d +++ b/tests/dmd/fail_compilation/fail7603c.d @@ -1,7 +1,7 @@ /* TEST_OUTPUT: --- -fail_compilation/fail7603c.d(8): Error: cannot modify constant `3` +fail_compilation/fail7603c.d(8): Error: cannot create default argument for `ref` / `out` parameter from constant `3` --- */ enum x = 3; diff --git a/tests/dmd/fail_compilation/fail9537.d b/tests/dmd/fail_compilation/fail9537.d index e08badf34a9..4d593e39ddb 100644 --- a/tests/dmd/fail_compilation/fail9537.d +++ b/tests/dmd/fail_compilation/fail9537.d @@ -1,7 +1,7 @@ /* TEST_OUTPUT: --- -fail_compilation/fail9537.d(26): Error: `foo(tuple(1, 2))` is not an lvalue and cannot be modified +fail_compilation/fail9537.d(26): Error: cannot take address of expression `foo(tuple(1, 2))` because it is not an lvalue --- */ diff --git a/tests/dmd/fail_compilation/fail9773.d b/tests/dmd/fail_compilation/fail9773.d index b49ffe13dfc..26447a73914 100644 --- a/tests/dmd/fail_compilation/fail9773.d +++ b/tests/dmd/fail_compilation/fail9773.d @@ -1,7 +1,7 @@ /* TEST_OUTPUT: --- -fail_compilation/fail9773.d(7): Error: `""` is not an lvalue and cannot be modified +fail_compilation/fail9773.d(7): Error: cannot create default argument for `ref` / `out` parameter from expression `""` because it is not an lvalue --- */ void f(ref string a = "") diff --git a/tests/dmd/fail_compilation/fail9891.d b/tests/dmd/fail_compilation/fail9891.d index 791e734349f..0c2384fccfa 100644 --- a/tests/dmd/fail_compilation/fail9891.d +++ b/tests/dmd/fail_compilation/fail9891.d @@ -3,7 +3,7 @@ TEST_OUTPUT: --- fail_compilation/fail9891.d(13): Error: expression `i` of type `immutable(int)` is not implicitly convertible to type `ref int` of parameter `n` fail_compilation/fail9891.d(18): Error: expression `i` of type `immutable(int)` is not implicitly convertible to type `out int` of parameter `n` -fail_compilation/fail9891.d(23): Error: `prop()` is not an lvalue and cannot be modified +fail_compilation/fail9891.d(23): Error: cannot create default argument for `ref` / `out` parameter from expression `prop()` because it is not an lvalue --- */ diff --git a/tests/dmd/fail_compilation/fail_arrayop2.d b/tests/dmd/fail_compilation/fail_arrayop2.d index c3c735ed552..0db6a45c9a2 100644 --- a/tests/dmd/fail_compilation/fail_arrayop2.d +++ b/tests/dmd/fail_compilation/fail_arrayop2.d @@ -207,21 +207,21 @@ fail_compilation/fail_arrayop2.d(265): Error: array operation `[1] * 6` without fail_compilation/fail_arrayop2.d(268): Error: array operation `[1] * 6` without destination memory not allowed fail_compilation/fail_arrayop2.d(269): Error: array operation `"abc"[] + '\x01'` without destination memory not allowed fail_compilation/fail_arrayop2.d(272): Error: array operation `[1] * 6` without destination memory not allowed -fail_compilation/fail_arrayop2.d(275): Error: `([1] * 6)[0..2]` is not an lvalue and cannot be modified +fail_compilation/fail_arrayop2.d(275): Error: cannot take address of expression `([1] * 6)[0..2]` because it is not an lvalue fail_compilation/fail_arrayop2.d(278): Error: can only `*` a pointer, not a `int[]` fail_compilation/fail_arrayop2.d(281): Error: the `delete` keyword is obsolete fail_compilation/fail_arrayop2.d(281): use `object.destroy()` (and `core.memory.GC.free()` if applicable) instead fail_compilation/fail_arrayop2.d(284): Error: array operation `da[] * 6` without destination memory not allowed fail_compilation/fail_arrayop2.d(287): Error: array operation `da[] * 6` without destination memory not allowed -fail_compilation/fail_arrayop2.d(290): Error: `[1] * 6` is not an lvalue and cannot be modified +fail_compilation/fail_arrayop2.d(290): Error: cannot modify expression `[1] * 6` because it is not an lvalue fail_compilation/fail_arrayop2.d(291): Error: array operation `[1] * 6` without destination memory not allowed -fail_compilation/fail_arrayop2.d(294): Error: `[1] * 6` is not an lvalue and cannot be modified -fail_compilation/fail_arrayop2.d(295): Error: `([1] * 6)[]` is not an lvalue and cannot be modified +fail_compilation/fail_arrayop2.d(294): Error: cannot modify expression `[1] * 6` because it is not an lvalue +fail_compilation/fail_arrayop2.d(295): Error: cannot modify expression `([1] * 6)[]` because it is not an lvalue fail_compilation/fail_arrayop2.d(298): Error: array operation `[1] * 6` without destination memory not allowed fail_compilation/fail_arrayop2.d(299): Error: array operation `[1] * 6` without destination memory not allowed fail_compilation/fail_arrayop2.d(300): Error: array operation `[1] * 6` without destination memory not allowed -fail_compilation/fail_arrayop2.d(303): Error: `[1] * 6` is not an lvalue and cannot be modified -fail_compilation/fail_arrayop2.d(304): Error: `[1] * 6` is not an lvalue and cannot be modified +fail_compilation/fail_arrayop2.d(303): Error: cannot modify expression `[1] * 6` because it is not an lvalue +fail_compilation/fail_arrayop2.d(304): Error: cannot modify expression `[1] * 6` because it is not an lvalue fail_compilation/fail_arrayop2.d(307): Error: `[1] * 6` is not of integral type, it is a `int[]` fail_compilation/fail_arrayop2.d(308): Error: `[1] * 6` is not of integral type, it is a `int[]` fail_compilation/fail_arrayop2.d(309): Error: `[1] * 6` is not of integral type, it is a `int[]` diff --git a/tests/dmd/fail_compilation/failcstuff2.c b/tests/dmd/fail_compilation/failcstuff2.c index 44fa9e6afcb..fe86b7206ea 100644 --- a/tests/dmd/fail_compilation/failcstuff2.c +++ b/tests/dmd/fail_compilation/failcstuff2.c @@ -1,23 +1,23 @@ // check semantic analysis of C files /* TEST_OUTPUT: --- -fail_compilation/failcstuff2.c(113): Error: `cast(int)var` is not an lvalue and cannot be modified +fail_compilation/failcstuff2.c(113): Error: cannot modify expression `cast(int)var` because it is not an lvalue fail_compilation/failcstuff2.c(114): Error: `sizeof` is not a member of `int` -fail_compilation/failcstuff2.c(115): Error: `cast(short)3` is not an lvalue and cannot be modified +fail_compilation/failcstuff2.c(115): Error: cannot modify expression `cast(short)3` because it is not an lvalue fail_compilation/failcstuff2.c(116): Error: cannot modify constant `4` fail_compilation/failcstuff2.c(117): Error: cannot modify constant `5` -fail_compilation/failcstuff2.c(118): Error: cannot modify constant `6` -fail_compilation/failcstuff2.c(119): Error: `cast(int)var` is not an lvalue and cannot be modified -fail_compilation/failcstuff2.c(120): Error: `cast(int)var` is not an lvalue and cannot be modified -fail_compilation/failcstuff2.c(121): Error: `cast(int)var` is not an lvalue and cannot be modified -fail_compilation/failcstuff2.c(122): Error: `cast(int)var` is not an lvalue and cannot be modified -fail_compilation/failcstuff2.c(123): Error: `cast(int)var` is not an lvalue and cannot be modified -fail_compilation/failcstuff2.c(124): Error: `makeS22067().field` is not an lvalue and cannot be modified -fail_compilation/failcstuff2.c(125): Error: `makeS22067().field` is not an lvalue and cannot be modified -fail_compilation/failcstuff2.c(126): Error: `makeS22067().field` is not an lvalue and cannot be modified -fail_compilation/failcstuff2.c(127): Error: `makeS22067().field` is not an lvalue and cannot be modified -fail_compilation/failcstuff2.c(153): Error: `cast(short)var` is not an lvalue and cannot be modified -fail_compilation/failcstuff2.c(154): Error: `cast(long)var` is not an lvalue and cannot be modified +fail_compilation/failcstuff2.c(118): Error: cannot take address of constant `6` +fail_compilation/failcstuff2.c(119): Error: cannot modify expression `cast(int)var` because it is not an lvalue +fail_compilation/failcstuff2.c(120): Error: cannot modify expression `cast(int)var` because it is not an lvalue +fail_compilation/failcstuff2.c(121): Error: cannot modify expression `cast(int)var` because it is not an lvalue +fail_compilation/failcstuff2.c(122): Error: cannot modify expression `cast(int)var` because it is not an lvalue +fail_compilation/failcstuff2.c(123): Error: cannot take address of expression `cast(int)var` because it is not an lvalue +fail_compilation/failcstuff2.c(124): Error: cannot take address of expression `makeS22067().field` because it is not an lvalue +fail_compilation/failcstuff2.c(125): Error: cannot modify expression `makeS22067().field` because it is not an lvalue +fail_compilation/failcstuff2.c(126): Error: cannot modify expression `makeS22067().field` because it is not an lvalue +fail_compilation/failcstuff2.c(127): Error: cannot modify expression `makeS22067().field` because it is not an lvalue +fail_compilation/failcstuff2.c(153): Error: cannot modify expression `cast(short)var` because it is not an lvalue +fail_compilation/failcstuff2.c(154): Error: cannot modify expression `cast(long)var` because it is not an lvalue fail_compilation/failcstuff2.c(354): Error: variable `arr` cannot be read at compile time fail_compilation/failcstuff2.c(360): Error: variable `str` cannot be read at compile time fail_compilation/failcstuff2.c(352): Error: cannot take address of register variable `reg1` diff --git a/tests/dmd/fail_compilation/ice10419.d b/tests/dmd/fail_compilation/ice10419.d index 827f0451824..fed8c608569 100644 --- a/tests/dmd/fail_compilation/ice10419.d +++ b/tests/dmd/fail_compilation/ice10419.d @@ -1,7 +1,7 @@ /* TEST_OUTPUT: --- -fail_compilation/ice10419.d(12): Error: `arr().length` is not an lvalue and cannot be modified +fail_compilation/ice10419.d(12): Error: cannot modify expression `arr().length` because it is not an lvalue --- */ diff --git a/tests/dmd/fail_compilation/ice12841.d b/tests/dmd/fail_compilation/ice12841.d index c5894d2c7ee..343624dbc39 100644 --- a/tests/dmd/fail_compilation/ice12841.d +++ b/tests/dmd/fail_compilation/ice12841.d @@ -1,8 +1,8 @@ /* TEST_OUTPUT: --- -fail_compilation/ice12841.d(23): Error: `taskPool().amap(Args...)(Args args)` is not an lvalue and cannot be modified -fail_compilation/ice12841.d(24): Error: `amap(Args...)(Args args)` is not an lvalue and cannot be modified +fail_compilation/ice12841.d(23): Error: cannot take address of expression `taskPool().amap(Args...)(Args args)` because it is not an lvalue +fail_compilation/ice12841.d(24): Error: cannot take address of template `amap(Args...)(Args args)`, perhaps instantiate it first --- */ diff --git a/tests/dmd/fail_compilation/ice20264.d b/tests/dmd/fail_compilation/ice20264.d index 0d697e22c9f..df6667d9e4b 100644 --- a/tests/dmd/fail_compilation/ice20264.d +++ b/tests/dmd/fail_compilation/ice20264.d @@ -2,7 +2,7 @@ DISABLED: freebsd32 linux32 osx32 win32 TEST_OUTPUT: --- -fail_compilation/ice20264.d(12): Error: `cast(__vector(float[4]))a` is not an lvalue and cannot be modified +fail_compilation/ice20264.d(12): Error: cannot modify expression `cast(__vector(float[4]))a` because it is not an lvalue --- */ diff --git a/tests/dmd/fail_compilation/issue20704.d b/tests/dmd/fail_compilation/issue20704.d index 1e1f2e6f34b..ba91b063572 100644 --- a/tests/dmd/fail_compilation/issue20704.d +++ b/tests/dmd/fail_compilation/issue20704.d @@ -1,12 +1,12 @@ /* TEST_OUTPUT: --- -fail_compilation/issue20704.d(17): Error: cannot modify constant `0` +fail_compilation/issue20704.d(17): Error: cannot create default argument for `ref` / `out` parameter from constant `0` fail_compilation/issue20704.d(28): Error: template instance `issue20704.f2!int` error instantiating -fail_compilation/issue20704.d(19): Error: cannot modify constant `0` +fail_compilation/issue20704.d(19): Error: cannot create default argument for `ref` / `out` parameter from constant `0` fail_compilation/issue20704.d(30): Error: template instance `issue20704.f4!int` error instantiating -fail_compilation/issue20704.d(17): Error: `S(0)` is not an lvalue and cannot be modified +fail_compilation/issue20704.d(17): Error: cannot create default argument for `ref` / `out` parameter from expression `S(0)` because it is not an lvalue fail_compilation/issue20704.d(36): Error: template instance `issue20704.f2!(S)` error instantiating -fail_compilation/issue20704.d(17): Error: `null` is not an lvalue and cannot be modified +fail_compilation/issue20704.d(17): Error: cannot create default argument for `ref` / `out` parameter from expression `null` because it is not an lvalue fail_compilation/issue20704.d(38): Error: template instance `issue20704.f2!(C)` error instantiating --- */ diff --git a/tests/dmd/fail_compilation/test16381.d b/tests/dmd/fail_compilation/test16381.d index fd92798366c..5847e0459b6 100644 --- a/tests/dmd/fail_compilation/test16381.d +++ b/tests/dmd/fail_compilation/test16381.d @@ -2,7 +2,7 @@ REQUIRED_ARGS: -m64 TEST_OUTPUT: --- -fail_compilation/test16381.d(15): Error: `foo()` is not an lvalue and cannot be modified +fail_compilation/test16381.d(15): Error: cannot take address of expression `foo()` because it is not an lvalue --- */ diff --git a/tests/dmd/fail_compilation/test22070.c b/tests/dmd/fail_compilation/test22070.c index 3387ccef682..0aa32b23287 100644 --- a/tests/dmd/fail_compilation/test22070.c +++ b/tests/dmd/fail_compilation/test22070.c @@ -1,7 +1,7 @@ /* TEST_OUTPUT: --- -fail_compilation/test22070.c(10): Error: `&""` is not an lvalue and cannot be modified +fail_compilation/test22070.c(10): Error: cannot take address of expression `&""` because it is not an lvalue --- */ diff --git a/tests/dmd/fail_compilation/test24157.d b/tests/dmd/fail_compilation/test24157.d index 5022014a9a1..d78c9b628ef 100644 --- a/tests/dmd/fail_compilation/test24157.d +++ b/tests/dmd/fail_compilation/test24157.d @@ -3,8 +3,8 @@ /* TEST_OUTPUT: --- -fail_compilation/test24157.d(23): Error: `p.self()` is not an lvalue and cannot be modified -fail_compilation/test24157.d(27): Error: `p.unshared()` is not an lvalue and cannot be modified +fail_compilation/test24157.d(23): Error: cannot take address of expression `p.self()` because it is not an lvalue +fail_compilation/test24157.d(27): Error: cannot take address of expression `p.unshared()` because it is not an lvalue --- */ diff --git a/tests/dmd/fail_compilation/tolvalue.d b/tests/dmd/fail_compilation/tolvalue.d new file mode 100644 index 00000000000..e911dff7729 --- /dev/null +++ b/tests/dmd/fail_compilation/tolvalue.d @@ -0,0 +1,48 @@ +/** +TEST_OUTPUT: +--- +fail_compilation/tolvalue.d(28): Error: cannot take address of template `templateFunc(T)()`, perhaps instantiate it first +fail_compilation/tolvalue.d(29): Error: cannot take address of type `int` +fail_compilation/tolvalue.d(30): Error: cannot take address of constant `3` +fail_compilation/tolvalue.d(31): Error: cannot take address of operator `$` +fail_compilation/tolvalue.d(32): Error: cannot take address of compiler-generated variable `__ctfe` +fail_compilation/tolvalue.d(33): Error: cannot take address of manifest constant `f` +fail_compilation/tolvalue.d(38): Error: cannot create default argument for `ref` / `out` parameter from constant `3` +fail_compilation/tolvalue.d(39): Error: cannot create default argument for `ref` / `out` parameter from compiler-generated variable `__ctfe` +fail_compilation/tolvalue.d(40): Error: cannot create default argument for `ref` / `out` parameter from manifest constant `f` +fail_compilation/tolvalue.d(45): Error: cannot modify constant `3` +fail_compilation/tolvalue.d(46): Error: cannot modify compiler-generated variable `__ctfe` +fail_compilation/tolvalue.d(47): Error: cannot modify manifest constant `f` +--- +*/ + +// https://issues.dlang.org/show_bug.cgi?id=24238 + +void templateFunc(T)() {} +alias intAlias = int; +enum E { f } + +void addr() +{ + int[] a; + auto x0 = &templateFunc; + auto x1 = &intAlias; + auto x2 = &3; + auto x3 = a[&$]; + auto x4 = &__ctfe; + auto x6 = &E.f; +} + +void refArg() +{ + void f0(ref int = 3) {} + void f1(ref bool = __ctfe) {} + void f3(ref E = E.f) {} +} + +void inc(int lz) +{ + 3++; + __ctfe++; + E.f++; +} From 624f997d0faa3b81559e27503233665d0e34ac34 Mon Sep 17 00:00:00 2001 From: Dennis Korpel Date: Sun, 12 Nov 2023 21:32:29 +0100 Subject: [PATCH 022/215] Fix segfault in toLvalueImpl --- dmd/expressionsem.d | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/dmd/expressionsem.d b/dmd/expressionsem.d index 22b3fdaed2f..e749368c94c 100644 --- a/dmd/expressionsem.d +++ b/dmd/expressionsem.d @@ -15224,6 +15224,7 @@ private Expression toLvalueImpl(Expression _this, Scope* sc, const(char)* action if (!action) action = "create lvalue of"; + assert(e); Expression visit(Expression _this) { // BinaryAssignExp does not have an EXP associated @@ -15377,7 +15378,7 @@ private Expression toLvalueImpl(Expression _this, Scope* sc, const(char)* action Expression visitVectorArray(VectorArrayExp _this) { - _this.e1 = _this.e1.toLvalueImpl(sc, action, e); + _this.e1 = _this.e1.toLvalueImpl(sc, action, e ? e : _this.e1); return _this; } @@ -15402,13 +15403,13 @@ private Expression toLvalueImpl(Expression _this, Scope* sc, const(char)* action Expression visitDelegatePointer(DelegatePtrExp _this) { - _this.e1 = _this.e1.toLvalueImpl(sc, action, e); + _this.e1 = _this.e1.toLvalueImpl(sc, action, e ? e : _this.e1); return _this; } Expression visitDelegateFuncptr(DelegateFuncptrExp _this) { - _this.e1 = _this.e1.toLvalueImpl(sc, action, e); + _this.e1 = _this.e1.toLvalueImpl(sc, action, e ? e : _this.e1); return _this; } @@ -15666,7 +15667,7 @@ extern(C++) Expression modifiableLvalue(Expression _this, Scope* sc, Expression return ErrorExp.get(); } } - return exp.toLvalueImpl(sc, "modify", e); + return exp.toLvalueImpl(sc, "modify", e ? e : exp); } Expression visitString(StringExp exp) From 3767c7709e996737a9a6f52bdd6a8358a11bd398 Mon Sep 17 00:00:00 2001 From: Nick Treleaven Date: Mon, 13 Nov 2023 23:08:44 +0000 Subject: [PATCH 023/215] Fix aliasing function type returning a Type with TypeSuffixes (dlang/dmd!15805) Fix Issue 24206 - Can't alias a function type that returns a type with a TypeSuffix Add isTypeSuffix() function. This also means a function type with a TypeCtor is now deprecated, just like a function pointer type with a TypeCtor. This gives a better error message and simplifies the code. --- dmd/parse.d | 67 ++++++++++++++----------- tests/dmd/compilable/issue16020.d | 7 ++- tests/dmd/fail_compilation/fail21243.d | 18 +++---- tests/dmd/fail_compilation/issue16020.d | 8 +-- tests/dmd/fail_compilation/test22048.d | 2 +- 5 files changed, 56 insertions(+), 46 deletions(-) diff --git a/dmd/parse.d b/dmd/parse.d index 51e522d71e4..f9d174ab14f 100644 --- a/dmd/parse.d +++ b/dmd/parse.d @@ -4878,30 +4878,11 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer AST.Declaration v; AST.Dsymbol s; - // try to parse function type: - // TypeCtors? BasicType ( Parameters ) MemberFunctionAttributes bool attributesAppended; const StorageClass funcStc = parseTypeCtor(); - Token* tlu = &token; Token* tk; - if (token.value != TOK.function_ && - token.value != TOK.delegate_ && - isBasicType(&tlu) && tlu && - tlu.value == TOK.leftParenthesis) - { - AST.Type tret = parseBasicType(); - auto parameterList = parseParameterList(null); - - parseAttributes(); - if (udas) - error("user-defined attributes not allowed for `alias` declarations"); - - attributesAppended = true; - storage_class = appendStorageClass(storage_class, funcStc); - AST.Type tf = new AST.TypeFunction(parameterList, tret, link, storage_class); - v = new AST.AliasDeclaration(loc, ident, tf); - } - else if (token.value == TOK.function_ || + // function literal? + if (token.value == TOK.function_ || token.value == TOK.delegate_ || token.value == TOK.leftParenthesis && skipAttributes(peekPastParen(&token), &tk) && @@ -4911,10 +4892,10 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer token.value == TOK.ref_ && peekNext() == TOK.leftParenthesis && skipAttributes(peekPastParen(peek(&token)), &tk) && (tk.value == TOK.goesTo || tk.value == TOK.leftCurly) || - token.value == TOK.auto_ && peekNext() == TOK.ref_ && - peekNext2() == TOK.leftParenthesis && - skipAttributes(peekPastParen(peek(peek(&token))), &tk) && - (tk.value == TOK.goesTo || tk.value == TOK.leftCurly) + token.value == TOK.auto_ && + (peekNext() == TOK.leftParenthesis || // for better error + peekNext() == TOK.ref_ && + peekNext2() == TOK.leftParenthesis) ) { // function (parameters) { statements... } @@ -4955,21 +4936,46 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer } else { - parseAttributes(); // type + parseAttributes(); if (udas) error("user-defined attributes not allowed for `alias` declarations"); - auto t = parseType(); + auto t = parseBasicType(); + t = parseTypeSuffixes(t); + if (token.value == TOK.identifier) + { + error("unexpected identifier `%s` after `%s`", + token.ident.toChars(), t.toChars()); + nextToken(); + } + else if (token.value == TOK.leftParenthesis) + { + // function type: + // StorageClasses Type ( Parameters ) MemberFunctionAttributes + auto parameterList = parseParameterList(null); + udas = null; + parseStorageClasses(storage_class, link, setAlignment, ealign, udas, linkloc); + if (udas) + error("user-defined attributes not allowed for `alias` declarations"); + + attributesAppended = true; + // Note: method types can have a TypeCtor attribute + storage_class = appendStorageClass(storage_class, funcStc); + t = new AST.TypeFunction(parameterList, t, link, storage_class); + } // Disallow meaningless storage classes on type aliases if (storage_class) { // Don't raise errors for STC that are part of a function/delegate type, e.g. // `alias F = ref pure nothrow @nogc @safe int function();` - auto tp = t.isTypePointer; - const isFuncType = (tp && tp.next.isTypeFunction) || t.isTypeDelegate; - const remStc = isFuncType ? (storage_class & ~STC.FUNCATTR) : storage_class; + const remStc = t.isTypeFunction ? + storage_class & ~(STC.FUNCATTR | STC.TYPECTOR) : { + auto tp = t.isTypePointer; + const isFuncType = (tp && tp.next.isTypeFunction) || t.isTypeDelegate; + return isFuncType ? (storage_class & ~STC.FUNCATTR) : storage_class; + }(); if (remStc) { @@ -7217,6 +7223,7 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer return false; } + // pt = test token. If found, pt is set to the token after BasicType private bool isBasicType(Token** pt) { // This code parallels parseBasicType() diff --git a/tests/dmd/compilable/issue16020.d b/tests/dmd/compilable/issue16020.d index cfd078cdcd1..38a5d624320 100644 --- a/tests/dmd/compilable/issue16020.d +++ b/tests/dmd/compilable/issue16020.d @@ -1,3 +1,4 @@ +// function type aliases module issue16020; alias F1 = const(int)(); const(int) f1(){return 42;} @@ -36,4 +37,8 @@ alias Specialized = FunTemplate!int; alias Compared = void(int); static assert(is(Specialized == Compared)); -void main() {} +// type suffixes +alias FT = const(int)*(); +static assert(is(FT* == const(int)* function())); +alias FT2 = int*[2]() pure; +static assert(is(FT2* == int*[2] function() pure)); diff --git a/tests/dmd/fail_compilation/fail21243.d b/tests/dmd/fail_compilation/fail21243.d index 2e170d096c5..0b4117d5bc6 100644 --- a/tests/dmd/fail_compilation/fail21243.d +++ b/tests/dmd/fail_compilation/fail21243.d @@ -1,16 +1,12 @@ /+ TEST_OUTPUT: --- -fail_compilation/fail21243.d(16): Error: found `(` when expecting `ref` and function literal following `auto` -fail_compilation/fail21243.d(16): Error: semicolon expected following auto declaration, not `int` -fail_compilation/fail21243.d(16): Error: semicolon needed to end declaration of `x` instead of `)` -fail_compilation/fail21243.d(16): Error: declaration expected, not `)` -fail_compilation/fail21243.d(17): Error: `auto` can only be used as part of `auto ref` for function literal return values -fail_compilation/fail21243.d(18): Error: basic type expected, not `(` -fail_compilation/fail21243.d(18): Error: function declaration without return type. (Note that constructors are always named `this`) -fail_compilation/fail21243.d(18): Deprecation: storage class `auto` has no effect in type aliases -fail_compilation/fail21243.d(18): Error: semicolon expected to close `alias` declaration, not `=>` -fail_compilation/fail21243.d(18): Error: declaration expected, not `=>` -fail_compilation/fail21243.d(19): Error: `auto` can only be used as part of `auto ref` for function literal return values +fail_compilation/fail21243.d(12): Error: found `(` when expecting `ref` and function literal following `auto` +fail_compilation/fail21243.d(12): Error: semicolon expected following auto declaration, not `int` +fail_compilation/fail21243.d(12): Error: semicolon needed to end declaration of `x` instead of `)` +fail_compilation/fail21243.d(12): Error: declaration expected, not `)` +fail_compilation/fail21243.d(13): Error: `auto` can only be used as part of `auto ref` for function literal return values +fail_compilation/fail21243.d(14): Error: `auto` can only be used as part of `auto ref` for function literal return values +fail_compilation/fail21243.d(15): Error: `auto` can only be used as part of `auto ref` for function literal return values --- +/ auto a = auto (int x) => x; diff --git a/tests/dmd/fail_compilation/issue16020.d b/tests/dmd/fail_compilation/issue16020.d index fe4ad78f1ac..79eda2ea08c 100644 --- a/tests/dmd/fail_compilation/issue16020.d +++ b/tests/dmd/fail_compilation/issue16020.d @@ -1,9 +1,10 @@ /* TEST_OUTPUT: --- -fail_compilation/issue16020.d(12): Error: user-defined attributes not allowed for `alias` declarations -fail_compilation/issue16020.d(13): Error: semicolon expected to close `alias` declaration, not `(` -fail_compilation/issue16020.d(13): Error: declaration expected, not `(` +fail_compilation/issue16020.d(13): Error: user-defined attributes not allowed for `alias` declarations +fail_compilation/issue16020.d(14): Error: semicolon expected to close `alias` declaration, not `(` +fail_compilation/issue16020.d(14): Error: declaration expected, not `(` +fail_compilation/issue16020.d(15): Deprecation: storage class `final` has no effect in type aliases --- */ module issue16020; @@ -11,3 +12,4 @@ module issue16020; struct UDA{} alias Fun = @UDA void(); alias FunTemplate = void(T)(T t); +alias F2 = final int(); diff --git a/tests/dmd/fail_compilation/test22048.d b/tests/dmd/fail_compilation/test22048.d index e0560689f8d..72b91546a2b 100644 --- a/tests/dmd/fail_compilation/test22048.d +++ b/tests/dmd/fail_compilation/test22048.d @@ -3,7 +3,7 @@ /* TEST_OUTPUT: --- -fail_compilation/test22048.d(10): Error: unexpected identifier `p` in declarator +fail_compilation/test22048.d(10): Error: unexpected identifier `p` after `int` --- */ From 6a5ebece2c83ad6e3dc332ba465a79be54d16eb3 Mon Sep 17 00:00:00 2001 From: Walter Bright Date: Mon, 13 Nov 2023 22:19:47 -0800 Subject: [PATCH 024/215] switch to safe casts in ctfeexpr.d --- dmd/ctfeexpr.d | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/dmd/ctfeexpr.d b/dmd/ctfeexpr.d index c93269fb321..688c2ea072d 100644 --- a/dmd/ctfeexpr.d +++ b/dmd/ctfeexpr.d @@ -741,14 +741,14 @@ Expression pointerDifference(UnionExp* pue, const ref Loc loc, Type type, Expres Expression agg2 = getAggregateFromPointer(e2, &ofs2); if (agg1 == agg2) { - Type pointee = (cast(TypePointer)agg1.type).next; + Type pointee = agg1.type.nextOf(); const sz = pointee.size(); emplaceExp!(IntegerExp)(pue, loc, (ofs1 - ofs2) * sz, type); } else if (agg1.op == EXP.string_ && agg2.op == EXP.string_ && agg1.isStringExp().peekString().ptr == agg2.isStringExp().peekString().ptr) { - Type pointee = (cast(TypePointer)agg1.type).next; + Type pointee = agg1.type.nextOf(); const sz = pointee.size(); emplaceExp!(IntegerExp)(pue, loc, (ofs1 - ofs2) * sz, type); } @@ -794,14 +794,14 @@ Expression pointerArithmetic(UnionExp* pue, const ref Loc loc, EXP op, Type type goto Lcant; } dinteger_t ofs2 = e2.toInteger(); - Type pointee = (cast(TypeNext)agg1.type.toBasetype()).next; + Type pointee = agg1.type.toBasetype().nextOf(); dinteger_t sz = pointee.size(); sinteger_t indx; dinteger_t len; - if (agg1.op == EXP.symbolOffset) + if (auto soe = agg1.isSymOffExp()) { indx = ofs1 / sz; - len = (cast(TypeSArray)agg1.isSymOffExp().var.type).dim.toInteger(); + len = soe.var.type.isTypeSArray().dim.toInteger(); } else { @@ -836,9 +836,9 @@ Expression pointerArithmetic(UnionExp* pue, const ref Loc loc, EXP op, Type type error(loc, "CTFE internal error: pointer arithmetic `%s`", agg1.toChars()); goto Lcant; } - if (eptr.type.toBasetype().ty == Tsarray) + if (auto tsa = eptr.type.toBasetype().isTypeSArray()) { - dinteger_t dim = (cast(TypeSArray)eptr.type.toBasetype()).dim.toInteger(); + dinteger_t dim = tsa.dim.toInteger(); // Create a CTFE pointer &agg1[indx .. indx+dim] auto se = ctfeEmplaceExp!SliceExp(loc, agg1, ctfeEmplaceExp!IntegerExp(loc, indx, Type.tsize_t), @@ -2000,9 +2000,8 @@ void showCtfeExpr(Expression e, int level = 0) UnionExp voidInitLiteral(Type t, VarDeclaration var) { UnionExp ue; - if (t.ty == Tsarray) + if (auto tsa = t.isTypeSArray()) { - TypeSArray tsa = cast(TypeSArray)t; Expression elem = voidInitLiteral(tsa.next, var).copy(); // For aggregate value types (structs, static arrays) we must // create an a separate copy for each element. @@ -2019,9 +2018,8 @@ UnionExp voidInitLiteral(Type t, VarDeclaration var) ArrayLiteralExp ae = ue.exp().isArrayLiteralExp(); ae.ownedByCtfe = OwnedBy.ctfe; } - else if (t.ty == Tstruct) + else if (auto ts = t.isTypeStruct()) { - TypeStruct ts = cast(TypeStruct)t; auto exps = new Expressions(ts.sym.fields.length); foreach (size_t i; 0 .. ts.sym.fields.length) { From b7bd1ff9871424fdd4c096bad5d18afc2cfdad0a Mon Sep 17 00:00:00 2001 From: Walter Bright Date: Mon, 13 Nov 2023 22:36:20 -0800 Subject: [PATCH 025/215] ctfeexpr.d: use BitArray --- dmd/ctfeexpr.d | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/dmd/ctfeexpr.d b/dmd/ctfeexpr.d index 688c2ea072d..b5bcd7da574 100644 --- a/dmd/ctfeexpr.d +++ b/dmd/ctfeexpr.d @@ -28,6 +28,7 @@ import dmd.func; import dmd.globals; import dmd.location; import dmd.mtype; +import dmd.root.bitarray; import dmd.root.complex; import dmd.root.ctfloat; import dmd.root.port; @@ -1270,8 +1271,8 @@ private int ctfeRawCmp(const ref Loc loc, Expression e1, Expression e2, bool ide size_t dim = es1.keys.length; if (es2.keys.length != dim) return 1; - bool* used = cast(bool*)mem.xmalloc(bool.sizeof * dim); - memset(used, 0, bool.sizeof * dim); + BitArray used; + used.length = dim; foreach (size_t i; 0 .. dim) { Expression k1 = (*es1.keys)[i]; @@ -1290,11 +1291,9 @@ private int ctfeRawCmp(const ref Loc loc, Expression e1, Expression e2, bool ide } if (!v2 || ctfeRawCmp(loc, v1, v2, identity)) { - mem.xfree(used); return 1; } } - mem.xfree(used); return 0; } else if (e1.op == EXP.assocArrayLiteral && e2.op == EXP.null_) From cbba70d2b95afaf5d8472df50962e62c6fe76faf Mon Sep 17 00:00:00 2001 From: Walter Bright Date: Mon, 13 Nov 2023 23:35:02 -0800 Subject: [PATCH 026/215] merge templateParameterToBuffer() into toCBuffer() --- dmd/hdrgen.d | 16 +++++----------- 1 file changed, 5 insertions(+), 11 deletions(-) diff --git a/dmd/hdrgen.d b/dmd/hdrgen.d index 8325081dbd2..ee8374928d4 100644 --- a/dmd/hdrgen.d +++ b/dmd/hdrgen.d @@ -1943,7 +1943,7 @@ private void visitTemplateParameters(TemplateParameters* parameters, ref OutBuff { if (i) buf.writestring(", "); - p.templateParameterToBuffer(buf, &hgs); + toCBuffer(p, buf, hgs); } } @@ -2885,10 +2885,10 @@ void floatToBuffer(Type type, const real_t value, ref OutBuffer buf, const bool } } -private void templateParameterToBuffer(TemplateParameter tp, ref OutBuffer buf, HdrGenState* hgs) +void toCBuffer(const TemplateParameter tp, ref OutBuffer buf, ref HdrGenState hgs) { - scope v = new TemplateParameterPrettyPrintVisitor(&buf, hgs); - tp.accept(v); + scope v = new TemplateParameterPrettyPrintVisitor(&buf, &hgs); + (cast() tp).accept(v); } private extern (C++) final class TemplateParameterPrettyPrintVisitor : Visitor @@ -3262,12 +3262,6 @@ void argExpTypesToCBuffer(ref OutBuffer buf, Expressions* arguments) } } -void toCBuffer(const TemplateParameter tp, ref OutBuffer buf, ref HdrGenState hgs) -{ - scope v = new TemplateParameterPrettyPrintVisitor(&buf, &hgs); - (cast() tp).accept(v); -} - void arrayObjectsToBuffer(ref OutBuffer buf, Objects* objects) { if (!objects || !objects.length) @@ -3837,7 +3831,7 @@ private void visitFuncIdentWithPrefix(TypeFunction t, const Identifier ident, Te { if (i) buf.writestring(", "); - p.templateParameterToBuffer(buf, hgs); + toCBuffer(p, buf, *hgs); } buf.writeByte(')'); } From 439c4807fc7eacabed3abb4630c0033604e4d757 Mon Sep 17 00:00:00 2001 From: Walter Bright Date: Mon, 13 Nov 2023 22:59:35 -0800 Subject: [PATCH 027/215] ctfeexpr.d: use nothrow where we can --- dmd/ctfeexpr.d | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/dmd/ctfeexpr.d b/dmd/ctfeexpr.d index b5bcd7da574..43efc05b5d3 100644 --- a/dmd/ctfeexpr.d +++ b/dmd/ctfeexpr.d @@ -44,14 +44,14 @@ import dmd.visitor; extern (D) struct UnionExp { // yes, default constructor does nothing - extern (D) this(Expression e) + extern (D) this(Expression e) nothrow { memcpy(&this, cast(void*)e, e.size); } /* Extract pointer to Expression */ - extern (D) Expression exp() return + extern (D) Expression exp() return nothrow { return cast(Expression)&u; } @@ -110,7 +110,7 @@ void emplaceExp(T : Expression, Args...)(void* p, Args args) (cast(T)p).__ctor(args); } -void emplaceExp(T : UnionExp)(T* p, Expression e) +void emplaceExp(T : UnionExp)(T* p, Expression e) nothrow { memcpy(p, cast(void*)e, e.size); } @@ -135,7 +135,7 @@ void generateUncaughtError(ThrownExceptionExp tee) * Returns: * index of the field, or -1 if not found */ -int findFieldIndexByName(const StructDeclaration sd, const VarDeclaration v) pure @safe +int findFieldIndexByName(const StructDeclaration sd, const VarDeclaration v) pure @safe nothrow { foreach (i, field; sd.fields) { @@ -146,7 +146,7 @@ int findFieldIndexByName(const StructDeclaration sd, const VarDeclaration v) pur } // True if 'e' is CTFEExp::cantexp, or an exception -bool exceptionOrCantInterpret(const Expression e) @safe +bool exceptionOrCantInterpret(const Expression e) @safe nothrow { return e && (e.op == EXP.cantExpression || e.op == EXP.thrownException || e.op == EXP.showCtfeContext); } @@ -154,7 +154,7 @@ bool exceptionOrCantInterpret(const Expression e) @safe /************** Aggregate literals (AA/string/array/struct) ******************/ // Given expr, which evaluates to an array/AA/string literal, // return true if it needs to be copied -bool needToCopyLiteral(const Expression expr) +bool needToCopyLiteral(const Expression expr) nothrow { Expression e = cast()expr; for (;;) @@ -594,7 +594,7 @@ TypeAArray toBuiltinAAType(Type t) /************** TypeInfo operations ************************************/ // Return true if type is TypeInfo_Class -bool isTypeInfo_Class(const Type type) +bool isTypeInfo_Class(const Type type) nothrow { auto tc = cast()type.isTypeClass(); return tc && (Type.dtypeinfo == tc.sym || Type.dtypeinfo.isBaseOf(tc.sym, null)); @@ -979,7 +979,7 @@ bool isCtfeComparable(Expression e) } /// Map EXP comparison ops -private bool numCmp(N)(EXP op, N n1, N n2) +private bool numCmp(N)(EXP op, N n1, N n2) nothrow { switch (op) { @@ -998,25 +998,25 @@ private bool numCmp(N)(EXP op, N n1, N n2) } /// Returns cmp OP 0; where OP is ==, !=, <, >=, etc. Result is 0 or 1 -bool specificCmp(EXP op, int rawCmp) @safe +bool specificCmp(EXP op, int rawCmp) @safe nothrow { return numCmp!int(op, rawCmp, 0); } /// Returns e1 OP e2; where OP is ==, !=, <, >=, etc. Result is 0 or 1 -bool intUnsignedCmp(EXP op, dinteger_t n1, dinteger_t n2) @safe +bool intUnsignedCmp(EXP op, dinteger_t n1, dinteger_t n2) @safe nothrow { return numCmp!dinteger_t(op, n1, n2); } /// Returns e1 OP e2; where OP is ==, !=, <, >=, etc. Result is 0 or 1 -bool intSignedCmp(EXP op, sinteger_t n1, sinteger_t n2) @safe +bool intSignedCmp(EXP op, sinteger_t n1, sinteger_t n2) @safe nothrow { return numCmp!sinteger_t(op, n1, n2); } /// Returns e1 OP e2; where OP is ==, !=, <, >=, etc. Result is 0 or 1 -bool realCmp(EXP op, real_t r1, real_t r2) @safe +bool realCmp(EXP op, real_t r1, real_t r2) @safe nothrow { // Don't rely on compiler, handle NAN arguments separately if (CTFloat.isNaN(r1) || CTFloat.isNaN(r2)) // if unordered @@ -1106,7 +1106,7 @@ private int ctfeCmpArrays(const ref Loc loc, Expression e1, Expression e2, uinte /* Given a delegate expression e, return .funcptr. * If e is NullExp, return NULL. */ -private FuncDeclaration funcptrOf(Expression e) @safe +private FuncDeclaration funcptrOf(Expression e) @safe nothrow { assert(e.type.ty == Tdelegate); if (auto de = e.isDelegateExp()) @@ -1117,7 +1117,7 @@ private FuncDeclaration funcptrOf(Expression e) @safe return null; } -private bool isArray(const Expression e) @safe +private bool isArray(const Expression e) @safe nothrow { return e.op == EXP.arrayLiteral || e.op == EXP.string_ || e.op == EXP.slice || e.op == EXP.null_; } From cc638bdda1b4b26bae8549da208a1435bbb77595 Mon Sep 17 00:00:00 2001 From: Dennis Korpel Date: Tue, 14 Nov 2023 11:27:59 +0100 Subject: [PATCH 028/215] Refactor modifiableLvalue --- dmd/arrayop.d | 2 +- dmd/expression.h | 2 +- dmd/expressionsem.d | 39 ++++++++++++++++++++++++++------------- dmd/frontend.h | 2 +- dmd/iasmgcc.d | 2 +- 5 files changed, 30 insertions(+), 17 deletions(-) diff --git a/dmd/arrayop.d b/dmd/arrayop.d index 25bbb3f32ad..c3b8526a9a4 100644 --- a/dmd/arrayop.d +++ b/dmd/arrayop.d @@ -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); diff --git a/dmd/expression.h b/dmd/expression.h index 833db0403ee..2becd9adca2 100644 --- a/dmd/expression.h +++ b/dmd/expression.h @@ -53,7 +53,7 @@ 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, const char* action); -Expression *modifiableLvalue(Expression* exp, Scope *sc, Expression *e); +Expression *modifiableLvalue(Expression* exp, Scope *sc); typedef unsigned char OwnedBy; enum diff --git a/dmd/expressionsem.d b/dmd/expressionsem.d index e749368c94c..0ea4e22a6bd 100644 --- a/dmd/expressionsem.d +++ b/dmd/expressionsem.d @@ -7323,7 +7323,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor } exp.e1 = exp.e1.expressionSemantic(sc); - exp.e1 = exp.e1.modifiableLvalue(sc, exp.e1); + exp.e1 = exp.e1.modifiableLvalue(sc); exp.e1 = exp.e1.optimize(WANTvalue, /*keepLvalue*/ true); exp.type = exp.e1.type; @@ -8803,7 +8803,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor return; } exp.e1 = resolveProperties(sc, exp.e1); - exp.e1 = exp.e1.modifiableLvalue(sc, null); + exp.e1 = exp.e1.modifiableLvalue(sc); if (exp.e1.op == EXP.error) { result = exp.e1; @@ -10019,7 +10019,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor return; } - exp.e1 = exp.e1.modifiableLvalue(sc, exp.e1); + exp.e1 = exp.e1.modifiableLvalue(sc); exp.e1 = exp.e1.optimize(WANTvalue, /*keepLvalue*/ true); e = exp; @@ -10781,7 +10781,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor Expression ex; ex = new IndexExp(exp.loc, ea, ek); ex = ex.expressionSemantic(sc); - ex = ex.modifiableLvalue(sc, ex); // allocate new slot + ex = ex.modifiableLvalue(sc); // allocate new slot ex = ex.optimize(WANTvalue); ey = new ConstructExp(exp.loc, ex, ey); @@ -10974,7 +10974,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor { // e1 is not an lvalue, but we let code generator handle it - auto ale1x = ale.e1.modifiableLvalue(sc, exp.e1); + auto ale1x = ale.e1.modifiableLvalueImpl(sc, exp.e1); if (ale1x.op == EXP.error) return setResult(ale1x); ale.e1 = ale1x; @@ -11060,7 +11060,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor se = cast(SliceExp)se.e1; if (se.e1.op == EXP.question && se.e1.type.toBasetype().ty == Tsarray) { - se.e1 = se.e1.modifiableLvalue(sc, exp.e1); + se.e1 = se.e1.modifiableLvalueImpl(sc, exp.e1); if (se.e1.op == EXP.error) return setResult(se.e1); } @@ -11084,7 +11084,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor // Try to do a decent error message with the expression // before it gets constant folded if (exp.op == EXP.assign) - e1x = e1x.modifiableLvalue(sc, e1old); + e1x = e1x.modifiableLvalueImpl(sc, e1old); e1x = e1x.optimize(WANTvalue, /*keepLvalue*/ true); @@ -11532,7 +11532,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor } else { - exp.e1 = exp.e1.modifiableLvalue(sc, exp.e1); + exp.e1 = exp.e1.modifiableLvalue(sc); } if ((exp.e1.type.isintegral() || exp.e1.type.isfloating()) && (exp.e2.type.isintegral() || exp.e2.type.isfloating())) @@ -11591,7 +11591,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor } } - exp.e1 = exp.e1.modifiableLvalue(sc, exp.e1); + exp.e1 = exp.e1.modifiableLvalue(sc); if (exp.e1.op == EXP.error) { result = exp.e1; @@ -15627,7 +15627,20 @@ Modifiable checkModifiable(Expression exp, Scope* sc, ModifyFlags flag = ModifyF } } -extern(C++) Expression modifiableLvalue(Expression _this, Scope* sc, Expression e) +/** + * Similar to `toLvalue`, but also enforce it is mutable or raise an error. + * Params: + * _this = Expression to convert + * sc = scope + * Returns: `_this` converted to an lvalue, or an `ErrorExp` + */ +extern(C++) Expression modifiableLvalue(Expression _this, Scope* sc) +{ + return modifiableLvalueImpl(_this, sc, _this); +} + +// e = original / un-lowered expression to print in error messages +private Expression modifiableLvalueImpl(Expression _this, Scope* sc, Expression e) { Expression visit(Expression exp) { @@ -15716,7 +15729,7 @@ extern(C++) Expression modifiableLvalue(Expression _this, Scope* sc, Expression Expression visitComma(CommaExp exp) { - exp.e2 = exp.e2.modifiableLvalue(sc, e); + exp.e2 = exp.e2.modifiableLvalueImpl(sc, e); return exp; } @@ -15755,8 +15768,8 @@ extern(C++) Expression modifiableLvalue(Expression _this, Scope* sc, Expression error(exp.loc, "conditional expression `%s` is not a modifiable lvalue", exp.toChars()); return ErrorExp.get(); } - exp.e1 = exp.e1.modifiableLvalue(sc, exp.e1); - exp.e2 = exp.e2.modifiableLvalue(sc, exp.e2); + exp.e1 = exp.e1.modifiableLvalue(sc); + exp.e2 = exp.e2.modifiableLvalue(sc); return exp.toLvalue(sc, "modify"); } diff --git a/dmd/frontend.h b/dmd/frontend.h index 40265d07db2..3236524c5c9 100644 --- a/dmd/frontend.h +++ b/dmd/frontend.h @@ -7991,7 +7991,7 @@ extern Expression* expressionSemantic(Expression* e, Scope* sc); extern Expression* toLvalue(Expression* _this, Scope* sc, const char* action); -extern Expression* modifiableLvalue(Expression* _this, Scope* sc, Expression* e); +extern Expression* modifiableLvalue(Expression* _this, Scope* sc); extern const char* toChars(const Initializer* const i); diff --git a/dmd/iasmgcc.d b/dmd/iasmgcc.d index 276152da355..92837b45842 100644 --- a/dmd/iasmgcc.d +++ b/dmd/iasmgcc.d @@ -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; From 83c9b05adb8a9de2a26e375c989a7b1ecde74dcd Mon Sep 17 00:00:00 2001 From: Dennis Korpel Date: Tue, 14 Nov 2023 11:31:15 +0100 Subject: [PATCH 029/215] Remove redundant null checks --- dmd/expressionsem.d | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/dmd/expressionsem.d b/dmd/expressionsem.d index 0ea4e22a6bd..cd309523049 100644 --- a/dmd/expressionsem.d +++ b/dmd/expressionsem.d @@ -15378,7 +15378,7 @@ private Expression toLvalueImpl(Expression _this, Scope* sc, const(char)* action Expression visitVectorArray(VectorArrayExp _this) { - _this.e1 = _this.e1.toLvalueImpl(sc, action, e ? e : _this.e1); + _this.e1 = _this.e1.toLvalueImpl(sc, action, e); return _this; } @@ -15403,13 +15403,13 @@ private Expression toLvalueImpl(Expression _this, Scope* sc, const(char)* action Expression visitDelegatePointer(DelegatePtrExp _this) { - _this.e1 = _this.e1.toLvalueImpl(sc, action, e ? e : _this.e1); + _this.e1 = _this.e1.toLvalueImpl(sc, action, e); return _this; } Expression visitDelegateFuncptr(DelegateFuncptrExp _this) { - _this.e1 = _this.e1.toLvalueImpl(sc, action, e ? e : _this.e1); + _this.e1 = _this.e1.toLvalueImpl(sc, action, e); return _this; } @@ -15642,6 +15642,7 @@ extern(C++) Expression modifiableLvalue(Expression _this, Scope* sc) // e = original / un-lowered expression to print in error messages private Expression modifiableLvalueImpl(Expression _this, Scope* sc, Expression e) { + assert(e); Expression visit(Expression exp) { //printf("Expression::modifiableLvalue() %s, type = %s\n", exp.toChars(), exp.type.toChars()); @@ -15680,7 +15681,7 @@ private Expression modifiableLvalueImpl(Expression _this, Scope* sc, Expression return ErrorExp.get(); } } - return exp.toLvalueImpl(sc, "modify", e ? e : exp); + return exp.toLvalueImpl(sc, "modify", e); } Expression visitString(StringExp exp) From 42ec0ea4faa204c4651df362d19aa17e9bf44691 Mon Sep 17 00:00:00 2001 From: Dennis Korpel Date: Mon, 9 Oct 2023 12:27:04 +0200 Subject: [PATCH 030/215] Add scope flag for dip1000 and dip25 --- dmd/dscope.d | 20 ++++++- dmd/dsymbolsem.d | 2 +- dmd/escape.d | 22 ++++---- dmd/expressionsem.d | 4 +- dmd/func.d | 9 ++- dmd/scope.h | 3 + dmd/statementsem.d | 4 +- .../fail_compilation/dip1000_deprecation.d | 56 ------------------- tests/dmd/fail_compilation/fail_scope.d | 8 +-- 9 files changed, 50 insertions(+), 78 deletions(-) delete mode 100644 tests/dmd/fail_compilation/dip1000_deprecation.d diff --git a/dmd/dscope.d b/dmd/dscope.d index 3853512005c..f8a425d9329 100644 --- a/dmd/dscope.d +++ b/dmd/dscope.d @@ -66,13 +66,15 @@ enum SCOPE fullinst = 0x10000, /// fully instantiate templates ctfeBlock = 0x20000, /// inside a `if (__ctfe)` block + dip1000 = 0x40000, /// dip1000 errors enabled for this scope + dip25 = 0x80000, /// dip25 errors enabled for this scope } /// Flags that are carried along with a scope push() private enum PersistentFlags = SCOPE.contract | SCOPE.debug_ | SCOPE.ctfe | SCOPE.compile | SCOPE.constraint | SCOPE.noaccesscheck | SCOPE.ignoresymbolvisibility | - SCOPE.Cfile | SCOPE.ctfeBlock; + SCOPE.Cfile | SCOPE.ctfeBlock | SCOPE.dip1000 | SCOPE.dip25; extern (C++) struct Scope { @@ -176,6 +178,10 @@ extern (C++) struct Scope m = m.parent; m.addMember(null, sc.scopesym); m.parent = null; // got changed by addMember() + if (global.params.useDIP1000 == FeatureState.enabled) + sc.flags |= SCOPE.dip1000; + if (global.params.useDIP25 == FeatureState.enabled) + sc.flags |= SCOPE.dip25; if (_module.filetype == FileType.c) sc.flags |= SCOPE.Cfile; // Create the module scope underneath the global scope @@ -821,4 +827,16 @@ extern (C++) struct Scope { return (flags & (SCOPE.ctfe | SCOPE.ctfeBlock | SCOPE.compile)) == 0; } + + /// Returns: whether to raise DIP1000 warnings (FeatureStabe.default) or errors (FeatureState.enabled) + extern (D) FeatureState useDIP1000() + { + return (flags & SCOPE.dip1000) ? FeatureState.enabled : FeatureState.disabled; + } + + /// Returns: whether to raise DIP25 warnings (FeatureStabe.default) or errors (FeatureState.enabled) + extern (D) FeatureState useDIP25() + { + return (flags & SCOPE.dip25) ? FeatureState.enabled : FeatureState.disabled; + } } diff --git a/dmd/dsymbolsem.d b/dmd/dsymbolsem.d index d9515fe6b23..e5bf021d654 100644 --- a/dmd/dsymbolsem.d +++ b/dmd/dsymbolsem.d @@ -1141,7 +1141,7 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor else if (auto ale = ex.isArrayLiteralExp()) { // or an array literal assigned to a `scope` variable - if (global.params.useDIP1000 == FeatureState.enabled + if (sc.useDIP1000 == FeatureState.enabled && !dsym.type.nextOf().needsDestruction()) ale.onstack = true; } diff --git a/dmd/escape.d b/dmd/escape.d index 3f85ea08320..e25fc84234e 100644 --- a/dmd/escape.d +++ b/dmd/escape.d @@ -25,7 +25,7 @@ import dmd.dsymbol; import dmd.errors; import dmd.expression; import dmd.func; -import dmd.globals; +import dmd.globals : FeatureState; import dmd.id; import dmd.identifier; import dmd.init; @@ -169,7 +169,7 @@ bool checkMutableArguments(Scope* sc, FuncDeclaration fd, TypeFunction tf, if (!(eb.isMutable || eb2.isMutable)) return; - if (!tf.islive && !(global.params.useDIP1000 == FeatureState.enabled && sc.func && sc.func.setUnsafe())) + if (!tf.islive && !(sc.useDIP1000 == FeatureState.enabled && sc.func && sc.func.setUnsafe())) return; if (!gag) @@ -377,7 +377,7 @@ bool checkParamArgumentEscape(Scope* sc, FuncDeclaration fdc, Identifier parId, sc.setUnsafeDIP1000(gag, arg.loc, msg, v, parId ? parId : fdc, fdc)) { result = true; - printScopeFailure(previewSupplementalFunc(sc.isDeprecated(), global.params.useDIP1000), vPar, 10); + printScopeFailure(previewSupplementalFunc(sc.isDeprecated(), sc.useDIP1000), vPar, 10); } } @@ -1094,7 +1094,7 @@ bool checkNewEscape(Scope* sc, Expression e, bool gag) { if (p == sc.func) { - result |= escapingRef(v, global.params.useDIP1000); + result |= escapingRef(v, sc.useDIP1000); continue; } } @@ -1110,7 +1110,7 @@ bool checkNewEscape(Scope* sc, Expression e, bool gag) { //printf("escaping reference to local ref variable %s\n", v.toChars()); //printf("storage class = x%llx\n", v.storage_class); - result |= escapingRef(v, global.params.useDIP25); + result |= escapingRef(v, sc.useDIP25); continue; } // Don't need to be concerned if v's parent does not return a ref @@ -1125,12 +1125,12 @@ bool checkNewEscape(Scope* sc, Expression e, bool gag) const(char)* msg = "storing reference to outer local variable `%s` into allocated memory causes it to escape"; if (!gag) { - previewErrorFunc(sc.isDeprecated(), global.params.useDIP25)(e.loc, msg, v.toChars()); + previewErrorFunc(sc.isDeprecated(), sc.useDIP25)(e.loc, msg, v.toChars()); } // If -preview=dip25 is used, the user wants an error // Otherwise, issue a deprecation - result |= (global.params.useDIP25 == FeatureState.enabled); + result |= (sc.useDIP25 == FeatureState.enabled); } } @@ -1264,7 +1264,7 @@ private bool checkReturnEscapeImpl(Scope* sc, Expression e, bool refs, bool gag) // https://issues.dlang.org/show_bug.cgi?id=23191 if (!gag) { - previewErrorFunc(sc.isDeprecated(), global.params.useDIP1000)(e.loc, + previewErrorFunc(sc.isDeprecated(), sc.useDIP1000)(e.loc, "scope parameter `%s` may not be returned", v.toChars() ); result = true; @@ -1403,7 +1403,7 @@ private bool checkReturnEscapeImpl(Scope* sc, Expression e, bool refs, bool gag) { //printf("escaping reference to local ref variable %s\n", v.toChars()); //printf("storage class = x%llx\n", v.storage_class); - escapingRef(v, global.params.useDIP25); + escapingRef(v, sc.useDIP25); continue; } // Don't need to be concerned if v's parent does not return a ref @@ -1415,7 +1415,7 @@ private bool checkReturnEscapeImpl(Scope* sc, Expression e, bool refs, bool gag) { const(char)* msg = "escaping reference to outer local variable `%s`"; if (!gag) - previewErrorFunc(sc.isDeprecated(), global.params.useDIP25)(e.loc, msg, v.toChars()); + previewErrorFunc(sc.isDeprecated(), sc.useDIP25)(e.loc, msg, v.toChars()); result = true; continue; } @@ -2588,7 +2588,7 @@ public bool setUnsafeDIP1000(Scope* sc, bool gag, Loc loc, const(char)* msg, RootObject arg0 = null, RootObject arg1 = null, RootObject arg2 = null) { - return setUnsafePreview(sc, global.params.useDIP1000, gag, loc, msg, arg0, arg1, arg2); + return setUnsafePreview(sc, sc.useDIP1000, gag, loc, msg, arg0, arg1, arg2); } /*************************************** diff --git a/dmd/expressionsem.d b/dmd/expressionsem.d index 22b3fdaed2f..9652d297b54 100644 --- a/dmd/expressionsem.d +++ b/dmd/expressionsem.d @@ -3209,7 +3209,7 @@ private bool functionParameters(const ref Loc loc, Scope* sc, const explicitScope = p.isLazy() || ((p.storageClass & STC.scope_) && !(p.storageClass & STC.scopeinferred)); if ((pStc & (STC.scope_ | STC.lazy_)) && - ((global.params.useDIP1000 == FeatureState.enabled) || explicitScope) && + ((sc.useDIP1000 == FeatureState.enabled) || explicitScope) && !(pStc & STC.return_)) { /* Argument value cannot escape from the called function. @@ -15797,7 +15797,7 @@ bool checkAddressVar(Scope* sc, Expression exp, VarDeclaration v) } if (sc.func && !sc.intypeof && !v.isDataseg()) { - if (global.params.useDIP1000 != FeatureState.enabled && + if (sc.useDIP1000 != FeatureState.enabled && !(v.storage_class & STC.temp) && sc.setUnsafe(false, exp.loc, "cannot take address of local `%s` in `@safe` function `%s`", v, sc.func)) { diff --git a/dmd/func.d b/dmd/func.d index edf113e2160..c59126e8d12 100644 --- a/dmd/func.d +++ b/dmd/func.d @@ -4621,7 +4621,14 @@ bool setUnsafePreview(Scope* sc, FeatureState fs, bool gag, Loc loc, const(char) case default_: if (!sc.func) return false; - if (!sc.func.isSafeBypassingInference() && !sc.func.safetyViolation) + if (sc.func.isSafeBypassingInference()) + { + if (!gag) + { + warning(loc, msg, arg0 ? arg0.toChars() : "", arg1 ? arg1.toChars() : "", arg2 ? arg2.toChars() : ""); + } + } + else if (!sc.func.safetyViolation) { import dmd.func : AttributeViolation; sc.func.safetyViolation = new AttributeViolation(loc, msg, arg0, arg1, arg2); diff --git a/dmd/scope.h b/dmd/scope.h index 178542e37b0..9c9aea9acb6 100644 --- a/dmd/scope.h +++ b/dmd/scope.h @@ -61,6 +61,9 @@ enum class SCOPE Cfile = 0x0800, // C semantics apply free = 0x8000, // is on free list fullinst = 0x10000, // fully instantiate templates + ctfeBlock = 0x20000, // inside a `if (__ctfe)` block + dip1000 = 0x40000, // dip1000 errors enabled for this scope + dip25 = 0x80000, // dip25 errors enabled for this scope }; struct Scope diff --git a/dmd/statementsem.d b/dmd/statementsem.d index f8b2c26df7f..3873adc82ee 100644 --- a/dmd/statementsem.d +++ b/dmd/statementsem.d @@ -3801,7 +3801,7 @@ private extern(D) Expression applyOpApply(ForeachStatement fs, Expression flde, { version (none) { - if (global.params.useDIP1000 == FeatureState.enabled) + if (sc2.useDIP1000 == FeatureState.enabled) { message(loc, "To enforce `@safe`, the compiler allocates a closure unless `opApply()` uses `scope`"); } @@ -3809,7 +3809,7 @@ private extern(D) Expression applyOpApply(ForeachStatement fs, Expression flde, } else { - if (global.params.useDIP1000 == FeatureState.enabled) + if (sc2.useDIP1000 == FeatureState.enabled) ++(cast(FuncExp)flde).fd.tookAddressOf; // allocate a closure unless the opApply() uses 'scope' } assert(tab.ty == Tstruct || tab.ty == Tclass); diff --git a/tests/dmd/fail_compilation/dip1000_deprecation.d b/tests/dmd/fail_compilation/dip1000_deprecation.d deleted file mode 100644 index 77ab52046fc..00000000000 --- a/tests/dmd/fail_compilation/dip1000_deprecation.d +++ /dev/null @@ -1,56 +0,0 @@ -/* -REQUIRED_ARGS: -de -TEST_OUTPUT: ---- -fail_compilation/dip1000_deprecation.d(17): Deprecation: `@safe` function `main` calling `inferred` -fail_compilation/dip1000_deprecation.d(25): which wouldn't be `@safe` because of: -fail_compilation/dip1000_deprecation.d(25): scope variable `x0` may not be returned -fail_compilation/dip1000_deprecation.d(19): Deprecation: `@safe` function `main` calling `inferredC` -fail_compilation/dip1000_deprecation.d(36): which calls `dip1000_deprecation.inferred` -fail_compilation/dip1000_deprecation.d(25): which wouldn't be `@safe` because of: -fail_compilation/dip1000_deprecation.d(25): scope variable `x0` may not be returned ---- -*/ - -void main() @safe -{ - cast(void)inferred(); - cast(void)inferredB(); // no deprecation, trusted - cast(void)inferredC(); // nested deprecation -} - -auto inferred() -{ - scope int* x0; - return x0; -} - -auto inferredB() @trusted -{ - scope int* x1; - return x1; -} - -auto inferredC() -{ - return inferred(); // no deprecation, inferredC is not explicit `@safe` -} - -@safe: - -struct S -{ - int* ptr; - int* incorrectReturnRef() scope return @trusted {return ptr;} -} - -S createS() { return S.init; } - -int* escape(int i) -{ - if (i) return S().incorrectReturnRef(); - if (i) return createS().incorrectReturnRef(); - - S s; - return s.incorrectReturnRef(); -} diff --git a/tests/dmd/fail_compilation/fail_scope.d b/tests/dmd/fail_compilation/fail_scope.d index a9e5429366a..9851ffc1c74 100644 --- a/tests/dmd/fail_compilation/fail_scope.d +++ b/tests/dmd/fail_compilation/fail_scope.d @@ -1,10 +1,6 @@ /* TEST_OUTPUT: --- -fail_compilation/fail_scope.d(28): Deprecation: scope parameter `da` may not be returned -fail_compilation/fail_scope.d(30): Deprecation: scope parameter `o` may not be returned -fail_compilation/fail_scope.d(31): Deprecation: scope parameter `dg` may not be returned -fail_compilation/fail_scope.d(38): Deprecation: scope parameter `p` may not be returned fail_compilation/fail_scope.d(43): Error: returning `cast(char[])string` escapes a reference to local variable `string` fail_compilation/fail_scope.d(61): Error: returning `s.bar()` escapes a reference to local variable `s` fail_compilation/fail_scope.d(72): Error: `fail_scope.foo8` called with argument types `(int)` matches both: @@ -23,6 +19,10 @@ fail_compilation/fail_scope.d(135): Error: returning `foo16226(i)` escapes a ref //fail_compilation/fail_scope.d(40): Error: scope variable `p` may not be returned */ + + + + alias int delegate() dg_t; int[] checkEscapeScope1(scope int[] da) { return da; } From a66f909d012eec9d41b08fb21951167f16c879e9 Mon Sep 17 00:00:00 2001 From: Dennis Date: Tue, 14 Nov 2023 14:04:36 +0100 Subject: [PATCH 031/215] Fix _Float32x and _Float64x aliases (dlang/dmd!15813) --- runtime/druntime/src/importc.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/runtime/druntime/src/importc.h b/runtime/druntime/src/importc.h index 3aaff2baf2e..ee80be8177c 100644 --- a/runtime/druntime/src/importc.h +++ b/runtime/druntime/src/importc.h @@ -153,9 +153,9 @@ #ifndef __aarch64__ #define _Float32 float -#define _Float32x float +#define _Float32x double #define _Float64 double -#define _Float64x double +#define _Float64x long double #define _Float128 long double #define __float128 long double #endif From 6595729cffd7d7b471637b284924bce4b7cf60af Mon Sep 17 00:00:00 2001 From: Nick Treleaven Date: Tue, 14 Nov 2023 17:29:15 +0000 Subject: [PATCH 032/215] Show `TypeFunction.mod` in overload candidates Fix Issue 22216 - Incomplete/incorrect error message for mutability overloads --- dmd/common/outbuffer.d | 6 +++--- dmd/func.d | 14 +++++++++---- tests/dmd/fail_compilation/ctor_attr.d | 27 ++++++++++++++++++++++++++ tests/dmd/fail_compilation/diag10415.d | 2 +- tests/dmd/fail_compilation/ice13459.d | 2 +- 5 files changed, 42 insertions(+), 9 deletions(-) create mode 100644 tests/dmd/fail_compilation/ctor_attr.d diff --git a/dmd/common/outbuffer.d b/dmd/common/outbuffer.d index b8ad7851e4d..4e7a82fb565 100644 --- a/dmd/common/outbuffer.d +++ b/dmd/common/outbuffer.d @@ -281,7 +281,7 @@ struct OutBuffer write(&v, v.sizeof); } - /// NOT zero-terminated + /// Buffer will NOT be zero-terminated extern (C++) void writestring(const(char)* s) pure nothrow @system { if (!s) @@ -302,14 +302,14 @@ struct OutBuffer write(s); } - /// NOT zero-terminated, followed by newline + /// Buffer will NOT be zero-terminated, followed by newline void writestringln(const(char)[] s) pure nothrow @safe { writestring(s); writenl(); } - /** Write string to buffer, ensure it is zero terminated + /** Write C string AND null byte */ void writeStringz(const(char)* s) pure nothrow @system { diff --git a/dmd/func.d b/dmd/func.d index edf113e2160..a55f77864fb 100644 --- a/dmd/func.d +++ b/dmd/func.d @@ -3535,11 +3535,17 @@ if (is(Decl == TemplateDeclaration) || is(Decl == FuncDeclaration)) if (!print) return true; auto tf = cast(TypeFunction) fd.type; + OutBuffer buf; + buf.writestring(fd.toPrettyChars()); + buf.writestring(parametersTypeToChars(tf.parameterList)); + if (tf.mod) + { + buf.writeByte(' '); + buf.MODtoBuffer(tf.mod); + } .errorSupplemental(fd.loc, - printed ? " `%s%s`" : - single_candidate ? "Candidate is: `%s%s`" : "Candidates are: `%s%s`", - fd.toPrettyChars(), - parametersTypeToChars(tf.parameterList)); + printed ? " `%s`" : + single_candidate ? "Candidate is: `%s`" : "Candidates are: `%s`", buf.peekChars()); } else if (auto td = s.isTemplateDeclaration()) { diff --git a/tests/dmd/fail_compilation/ctor_attr.d b/tests/dmd/fail_compilation/ctor_attr.d new file mode 100644 index 00000000000..da5a30cddfc --- /dev/null +++ b/tests/dmd/fail_compilation/ctor_attr.d @@ -0,0 +1,27 @@ +/* +TEST_OUTPUT: +--- +fail_compilation/ctor_attr.d(24): Error: none of the overloads of `this` are callable using argument types `(int)` +fail_compilation/ctor_attr.d(15): Candidates are: `ctor_attr.S.this(int x) const` +fail_compilation/ctor_attr.d(16): `ctor_attr.S.this(string x)` +fail_compilation/ctor_attr.d(26): Error: none of the overloads of `foo` are callable using a mutable object +fail_compilation/ctor_attr.d(18): Candidates are: `ctor_attr.S.foo(int x) immutable` +fail_compilation/ctor_attr.d(19): `ctor_attr.S.foo(string x)` +--- +*/ + +struct S +{ + this(int x) const {} + this(string x) {} + + void foo(int x) immutable {} + void foo(string x) {} +} + +void f() +{ + auto s = S(1); + S t; + t.foo(1); +} diff --git a/tests/dmd/fail_compilation/diag10415.d b/tests/dmd/fail_compilation/diag10415.d index 207f6a4aa15..74444327ecb 100644 --- a/tests/dmd/fail_compilation/diag10415.d +++ b/tests/dmd/fail_compilation/diag10415.d @@ -2,7 +2,7 @@ TEST_OUTPUT: --- fail_compilation/diag10415.d(36): Error: none of the overloads of `x` are callable using argument types `(int) const` -fail_compilation/diag10415.d(13): Candidates are: `diag10415.C.x()` +fail_compilation/diag10415.d(13): Candidates are: `diag10415.C.x() const` fail_compilation/diag10415.d(18): `diag10415.C.x(int __param_0)` fail_compilation/diag10415.d(39): Error: d.x is not an lvalue --- diff --git a/tests/dmd/fail_compilation/ice13459.d b/tests/dmd/fail_compilation/ice13459.d index d34fc60db6a..6998e685a75 100644 --- a/tests/dmd/fail_compilation/ice13459.d +++ b/tests/dmd/fail_compilation/ice13459.d @@ -3,7 +3,7 @@ TEST_OUTPUT: --- fail_compilation/ice13459.d(12): Error: undefined identifier `B` fail_compilation/ice13459.d(18): Error: none of the overloads of `opSlice` are callable using argument types `(int, int)` -fail_compilation/ice13459.d(11): Candidate is: `ice13459.A.opSlice()` +fail_compilation/ice13459.d(11): Candidate is: `ice13459.A.opSlice() const` --- */ struct A From b0e9715712d7794877e7aeb0eae22db7f1c56f91 Mon Sep 17 00:00:00 2001 From: Nick Treleaven Date: Tue, 14 Nov 2023 18:33:03 +0000 Subject: [PATCH 033/215] Show template function attribute --- dmd/dtemplate.d | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/dmd/dtemplate.d b/dmd/dtemplate.d index 883f4ac94cf..9a2e6edbc6a 100644 --- a/dmd/dtemplate.d +++ b/dmd/dtemplate.d @@ -762,6 +762,11 @@ extern (C++) final class TemplateDeclaration : ScopeDsymbol { TypeFunction tf = cast(TypeFunction)fd.type; buf.writestring(parametersTypeToChars(tf.parameterList)); + if (tf.mod) + { + buf.writeByte(' '); + buf.MODtoBuffer(tf.mod); + } } } From 5274e8ef3bac465f4628006c12eb39e445581bfc Mon Sep 17 00:00:00 2001 From: Nick Treleaven Date: Tue, 14 Nov 2023 18:36:38 +0000 Subject: [PATCH 034/215] Fix __ctor ident --- dmd/dtemplate.d | 2 +- tests/dmd/fail_compilation/ice9284.d | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/dmd/dtemplate.d b/dmd/dtemplate.d index 9a2e6edbc6a..398b817e476 100644 --- a/dmd/dtemplate.d +++ b/dmd/dtemplate.d @@ -745,7 +745,7 @@ extern (C++) final class TemplateDeclaration : ScopeDsymbol OutBuffer buf; HdrGenState hgs; - buf.writestring(ident.toString()); + buf.writestring(ident == Id.ctor ? "this" : ident.toString()); buf.writeByte('('); foreach (i, const tp; *parameters) { diff --git a/tests/dmd/fail_compilation/ice9284.d b/tests/dmd/fail_compilation/ice9284.d index 47fd44c6b01..c9ab014b6e6 100644 --- a/tests/dmd/fail_compilation/ice9284.d +++ b/tests/dmd/fail_compilation/ice9284.d @@ -2,7 +2,7 @@ TEST_OUTPUT: --- fail_compilation/ice9284.d(14): Error: template `ice9284.C.__ctor` is not callable using argument types `!()(int)` -fail_compilation/ice9284.d(12): Candidate is: `__ctor()(string)` +fail_compilation/ice9284.d(12): Candidate is: `this()(string)` fail_compilation/ice9284.d(20): Error: template instance `ice9284.C.__ctor!()` error instantiating --- */ From af5c65e57e14e06b1f5252a69c09ad03c5f86e9c Mon Sep 17 00:00:00 2001 From: Nick Treleaven Date: Tue, 14 Nov 2023 18:37:11 +0000 Subject: [PATCH 035/215] Update tests --- tests/dmd/fail_compilation/ctor_attr.d | 14 ++++++++------ tests/dmd/fail_compilation/fail7424d.d | 2 +- tests/dmd/fail_compilation/fail7424e.d | 2 +- tests/dmd/fail_compilation/fail7424f.d | 2 +- tests/dmd/fail_compilation/fail7424i.d | 2 +- 5 files changed, 12 insertions(+), 10 deletions(-) diff --git a/tests/dmd/fail_compilation/ctor_attr.d b/tests/dmd/fail_compilation/ctor_attr.d index da5a30cddfc..2138af64bb5 100644 --- a/tests/dmd/fail_compilation/ctor_attr.d +++ b/tests/dmd/fail_compilation/ctor_attr.d @@ -1,18 +1,20 @@ /* TEST_OUTPUT: --- -fail_compilation/ctor_attr.d(24): Error: none of the overloads of `this` are callable using argument types `(int)` -fail_compilation/ctor_attr.d(15): Candidates are: `ctor_attr.S.this(int x) const` -fail_compilation/ctor_attr.d(16): `ctor_attr.S.this(string x)` -fail_compilation/ctor_attr.d(26): Error: none of the overloads of `foo` are callable using a mutable object -fail_compilation/ctor_attr.d(18): Candidates are: `ctor_attr.S.foo(int x) immutable` -fail_compilation/ctor_attr.d(19): `ctor_attr.S.foo(string x)` +fail_compilation/ctor_attr.d(26): Error: none of the overloads of `this` are callable using argument types `(int)` +fail_compilation/ctor_attr.d(16): Candidates are: `ctor_attr.S.this(int x) const` +fail_compilation/ctor_attr.d(18): `ctor_attr.S.this(string x)` +fail_compilation/ctor_attr.d(17): `this()(int x) shared` +fail_compilation/ctor_attr.d(28): Error: none of the overloads of `foo` are callable using a mutable object +fail_compilation/ctor_attr.d(20): Candidates are: `ctor_attr.S.foo(int x) immutable` +fail_compilation/ctor_attr.d(21): `ctor_attr.S.foo(string x)` --- */ struct S { this(int x) const {} + this()(int x) shared {} this(string x) {} void foo(int x) immutable {} diff --git a/tests/dmd/fail_compilation/fail7424d.d b/tests/dmd/fail_compilation/fail7424d.d index 38f47ba0913..920956bf2f9 100644 --- a/tests/dmd/fail_compilation/fail7424d.d +++ b/tests/dmd/fail_compilation/fail7424d.d @@ -1,7 +1,7 @@ /* TEST_OUTPUT: --- -fail_compilation/fail7424d.d(10): Error: template `this.g()()` has no value +fail_compilation/fail7424d.d(10): Error: template `this.g()() immutable` has no value --- */ struct S7424d diff --git a/tests/dmd/fail_compilation/fail7424e.d b/tests/dmd/fail_compilation/fail7424e.d index e92b4693d51..ddf9d1a89b3 100644 --- a/tests/dmd/fail_compilation/fail7424e.d +++ b/tests/dmd/fail_compilation/fail7424e.d @@ -1,7 +1,7 @@ /* TEST_OUTPUT: --- -fail_compilation/fail7424e.d(10): Error: template `this.g()()` has no value +fail_compilation/fail7424e.d(10): Error: template `this.g()() immutable` has no value --- */ struct S7424e diff --git a/tests/dmd/fail_compilation/fail7424f.d b/tests/dmd/fail_compilation/fail7424f.d index 1af14f83d7e..2f7f8f36153 100644 --- a/tests/dmd/fail_compilation/fail7424f.d +++ b/tests/dmd/fail_compilation/fail7424f.d @@ -1,7 +1,7 @@ /* TEST_OUTPUT: --- -fail_compilation/fail7424f.d(10): Error: template `this.g()()` has no value +fail_compilation/fail7424f.d(10): Error: template `this.g()() shared` has no value --- */ struct S7424f diff --git a/tests/dmd/fail_compilation/fail7424i.d b/tests/dmd/fail_compilation/fail7424i.d index 6352166add5..4e922d6f5be 100644 --- a/tests/dmd/fail_compilation/fail7424i.d +++ b/tests/dmd/fail_compilation/fail7424i.d @@ -1,7 +1,7 @@ /* TEST_OUTPUT: --- -fail_compilation/fail7424i.d(10): Error: template `this.g()()` has no value +fail_compilation/fail7424i.d(10): Error: template `this.g()() immutable` has no value --- */ struct S7424g From e8f4f06763b56d330811edb881c5253e24b77581 Mon Sep 17 00:00:00 2001 From: Nick Treleaven Date: Tue, 14 Nov 2023 18:59:36 +0000 Subject: [PATCH 036/215] More tests --- tests/dmd/compilable/diag20916.d | 2 +- tests/dmd/fail_compilation/testrvaluecpctor.d | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/dmd/compilable/diag20916.d b/tests/dmd/compilable/diag20916.d index ebdf3eec392..1993e0e0200 100644 --- a/tests/dmd/compilable/diag20916.d +++ b/tests/dmd/compilable/diag20916.d @@ -7,7 +7,7 @@ compilable/diag20916.d(42): instantiated from here: `jump1!(Foo)` compilable/diag20916.d(32): Deprecation: function `diag20916.FooBar.toString` is deprecated compilable/diag20916.d(37): instantiated from here: `jump2!(Foo)` compilable/diag20916.d(42): instantiated from here: `jump1!(Foo)` -compilable/diag20916.d(32): Deprecation: template `diag20916.Bar.toString()()` is deprecated +compilable/diag20916.d(32): Deprecation: template `diag20916.Bar.toString()() const` is deprecated compilable/diag20916.d(37): instantiated from here: `jump2!(Bar)` compilable/diag20916.d(43): instantiated from here: `jump1!(Bar)` compilable/diag20916.d(21): Deprecation: variable `diag20916.Something.something` is deprecated diff --git a/tests/dmd/fail_compilation/testrvaluecpctor.d b/tests/dmd/fail_compilation/testrvaluecpctor.d index 50cebabfda4..871159afa0c 100644 --- a/tests/dmd/fail_compilation/testrvaluecpctor.d +++ b/tests/dmd/fail_compilation/testrvaluecpctor.d @@ -7,7 +7,7 @@ fail_compilation/testrvaluecpctor.d(16): Error: cannot define both an rvalue con fail_compilation/testrvaluecpctor.d(24): Template instance `testrvaluecpctor.Foo!int.Foo.__ctor!(immutable(Foo!int), immutable(Foo!int))` creates an rvalue constructor for `struct Foo` fail_compilation/testrvaluecpctor.d(24): Error: none of the overloads of `__ctor` are callable using a `immutable` object fail_compilation/testrvaluecpctor.d(18): Candidates are: `testrvaluecpctor.Foo!int.Foo.this(ref scope Foo!int rhs)` -fail_compilation/testrvaluecpctor.d(16): `__ctor(Rhs, this This)(scope Rhs rhs)` +fail_compilation/testrvaluecpctor.d(16): `this(Rhs, this This)(scope Rhs rhs)` --- */ From 260abe16ff4a4e6325bb9a9b3c865d14aa1da2e1 Mon Sep 17 00:00:00 2001 From: Nick Treleaven Date: Tue, 14 Nov 2023 19:02:17 +0000 Subject: [PATCH 037/215] [trivial] [refactor] Use `TypeFunction.modToChars` --- dmd/func.d | 14 ++------------ 1 file changed, 2 insertions(+), 12 deletions(-) diff --git a/dmd/func.d b/dmd/func.d index c59126e8d12..5682608abcb 100644 --- a/dmd/func.d +++ b/dmd/func.d @@ -3241,13 +3241,6 @@ unittest assert(mismatches.isMutable); } -private const(char)* prependSpace(const(char)* str) -{ - if (!str || !*str) return ""; - - return (" " ~ str.toDString() ~ "\0").ptr; -} - /// Flag used by $(LREF resolveFuncCall). enum FuncResolveFlag : ubyte { @@ -3361,14 +3354,11 @@ FuncDeclaration resolveFuncCall(const ref Loc loc, Scope* sc, Dsymbol s, const(char)* lastprms = parametersTypeToChars(tf1.parameterList); const(char)* nextprms = parametersTypeToChars(tf2.parameterList); - const(char)* mod1 = prependSpace(MODtoChars(tf1.mod)); - const(char)* mod2 = prependSpace(MODtoChars(tf2.mod)); - .error(loc, "`%s.%s` called with argument types `%s` matches both:\n%s: `%s%s%s`\nand:\n%s: `%s%s%s`", s.parent.toPrettyChars(), s.ident.toChars(), fargsBuf.peekChars(), - m.lastf.loc.toChars(), m.lastf.toPrettyChars(), lastprms, mod1, - m.nextf.loc.toChars(), m.nextf.toPrettyChars(), nextprms, mod2); + m.lastf.loc.toChars(), m.lastf.toPrettyChars(), lastprms, tf1.modToChars(), + m.nextf.loc.toChars(), m.nextf.toPrettyChars(), nextprms, tf2.modToChars()); return null; } From 9684aed04f17bec000b1d01b6cc314266648d4e9 Mon Sep 17 00:00:00 2001 From: Walter Bright Date: Wed, 15 Nov 2023 13:04:42 -0800 Subject: [PATCH 038/215] fix Issue 24155 - ImportC: accept C23 default initializers (dlang/dmd!15801) --- dmd/astenums.d | 1 + dmd/cparse.d | 7 +++++++ dmd/frontend.h | 22 +++++++++++++++++----- dmd/hdrgen.d | 5 +++++ dmd/init.d | 29 +++++++++++++++++++++++++++++ dmd/init.h | 10 ++++++++++ dmd/initsem.d | 18 ++++++++++++++++++ dmd/parsetimevisitor.d | 1 + dmd/strictvisitor.d | 1 + dmd/visitor.h | 2 ++ tests/dmd/runnable/initializer.c | 25 +++++++++++++++++++++++++ 11 files changed, 116 insertions(+), 5 deletions(-) diff --git a/dmd/astenums.d b/dmd/astenums.d index 77f36f304a5..6a9c0104a72 100644 --- a/dmd/astenums.d +++ b/dmd/astenums.d @@ -383,6 +383,7 @@ enum STMT : ubyte enum InitKind : ubyte { void_, + default_, error, struct_, array, diff --git a/dmd/cparse.d b/dmd/cparse.d index f0c834972d6..ed5f1f8b9a2 100644 --- a/dmd/cparse.d +++ b/dmd/cparse.d @@ -2168,6 +2168,7 @@ final class CParser(AST) : Parser!AST * C11 Initialization * initializer: * assignment-expression + * { } // C23 6.7.10 addition * { initializer-list } * { initializer-list , } * @@ -2198,6 +2199,12 @@ final class CParser(AST) : Parser!AST nextToken(); const loc = token.loc; + if (token.value == TOK.rightCurly) // { } + { + nextToken(); + return new AST.DefaultInitializer(loc); + } + /* Collect one or more `designation (opt) initializer` * into ci.initializerList, but lazily create ci */ diff --git a/dmd/frontend.h b/dmd/frontend.h index 3236524c5c9..48e1eef513f 100644 --- a/dmd/frontend.h +++ b/dmd/frontend.h @@ -305,6 +305,7 @@ class TryCatchStatement; class DebugStatement; class ErrorInitializer; class VoidInitializer; +class DefaultInitializer; class StructInitializer; class ArrayInitializer; class ExpInitializer; @@ -1880,6 +1881,7 @@ class ParseTimeVisitor virtual void visit(typename AST::StructInitializer i); virtual void visit(typename AST::ArrayInitializer i); virtual void visit(typename AST::VoidInitializer i); + virtual void visit(typename AST::DefaultInitializer i); virtual void visit(typename AST::CInitializer i); }; @@ -2708,11 +2710,12 @@ extern const char* toChars(const Statement* const s); enum class InitKind : uint8_t { void_ = 0u, - error = 1u, - struct_ = 2u, - array = 3u, - exp = 4u, - C_ = 5u, + default_ = 1u, + error = 2u, + struct_ = 3u, + array = 4u, + exp = 5u, + C_ = 6u, }; class Initializer : public ASTNode @@ -2723,6 +2726,7 @@ class Initializer : public ASTNode DYNCAST dyncast() const override; ErrorInitializer* isErrorInitializer(); VoidInitializer* isVoidInitializer(); + DefaultInitializer* isDefaultInitializer(); StructInitializer* isStructInitializer(); ArrayInitializer* isArrayInitializer(); ExpInitializer* isExpInitializer(); @@ -2752,6 +2756,13 @@ class CInitializer final : public Initializer void accept(Visitor* v) override; }; +class DefaultInitializer final : public Initializer +{ +public: + Type* type; + void accept(Visitor* v) override; +}; + class ErrorInitializer final : public Initializer { public: @@ -4946,6 +4957,7 @@ struct ASTCodegen final using HdrGenState = ::HdrGenState; using ArrayInitializer = ::ArrayInitializer; using CInitializer = ::CInitializer; + using DefaultInitializer = ::DefaultInitializer; using DesigInit = ::DesigInit; using Designator = ::Designator; using ErrorInitializer = ::ErrorInitializer; diff --git a/dmd/hdrgen.d b/dmd/hdrgen.d index ee8374928d4..ac2dda3e89f 100644 --- a/dmd/hdrgen.d +++ b/dmd/hdrgen.d @@ -3856,6 +3856,11 @@ private void initializerToBuffer(Initializer inx, ref OutBuffer buf, HdrGenState buf.writestring("void"); } + void visitDefault(DefaultInitializer iz) + { + buf.writestring("{ }"); + } + void visitStruct(StructInitializer si) { //printf("StructInitializer::toCBuffer()\n"); diff --git a/dmd/init.d b/dmd/init.d index ebcd011f8a1..e48410082bd 100644 --- a/dmd/init.d +++ b/dmd/init.d @@ -68,6 +68,11 @@ extern (C++) class Initializer : ASTNode return kind == InitKind.void_ ? cast(inout VoidInitializer)cast(void*)this : null; } + final inout(DefaultInitializer) isDefaultInitializer() inout @nogc nothrow pure + { + return kind == InitKind.default_ ? cast(inout DefaultInitializer)cast(void*)this : null; + } + final inout(StructInitializer) isStructInitializer() inout @nogc nothrow pure { return kind == InitKind.struct_ ? cast(inout StructInitializer)cast(void*)this : null; @@ -111,6 +116,24 @@ extern (C++) final class VoidInitializer : Initializer } } +/*********************************************************** + * The C23 default initializer `{ }` + */ +extern (C++) final class DefaultInitializer : Initializer +{ + Type type; // type that this will initialize to + + extern (D) this(const ref Loc loc) @safe + { + super(loc, InitKind.default_); + } + + override void accept(Visitor v) + { + v.visit(this); + } +} + /*********************************************************** */ extern (C++) final class ErrorInitializer : Initializer @@ -266,6 +289,11 @@ Initializer syntaxCopy(Initializer inx) return new VoidInitializer(vi.loc); } + static Initializer visitDefault(DefaultInitializer vi) + { + return new DefaultInitializer(vi.loc); + } + static Initializer visitError(ErrorInitializer vi) { return vi; @@ -352,6 +380,7 @@ mixin template VisitInitializer(Result) final switch (init.kind) { case InitKind.void_: mixin(visitCase("Void")); break; + case InitKind.default_: mixin(visitCase("Default")); break; case InitKind.error: mixin(visitCase("Error")); break; case InitKind.struct_: mixin(visitCase("Struct")); break; case InitKind.array: mixin(visitCase("Array")); break; diff --git a/dmd/init.h b/dmd/init.h index 67d0527a3b2..21bd07f4f39 100644 --- a/dmd/init.h +++ b/dmd/init.h @@ -20,6 +20,7 @@ class Expression; class Type; class ErrorInitializer; class VoidInitializer; +class DefaultInitializer; class StructInitializer; class ArrayInitializer; class ExpInitializer; @@ -37,6 +38,7 @@ class Initializer : public ASTNode ErrorInitializer *isErrorInitializer(); VoidInitializer *isVoidInitializer(); + DefaultInitializer *isDefaultInitializer(); StructInitializer *isStructInitializer(); ArrayInitializer *isArrayInitializer(); ExpInitializer *isExpInitializer(); @@ -53,6 +55,14 @@ class VoidInitializer final : public Initializer void accept(Visitor *v) override { v->visit(this); } }; +class DefaultInitializer final : public Initializer +{ +public: + Type *type; // type that this will initialize to + + void accept(Visitor *v) override { v->visit(this); } +}; + class ErrorInitializer final : public Initializer { public: diff --git a/dmd/initsem.d b/dmd/initsem.d index 139db0f59e9..2d92cb87ec5 100644 --- a/dmd/initsem.d +++ b/dmd/initsem.d @@ -106,6 +106,7 @@ Expression toAssocArrayLiteral(ArrayInitializer ai) */ extern(C++) Initializer initializerSemantic(Initializer init, Scope* sc, ref Type tx, NeedInterpret needInterpret) { + //printf("initializerSemantic() tx: %p %s\n", tx, tx.toChars()); Type t = tx; static Initializer err() @@ -119,6 +120,12 @@ extern(C++) Initializer initializerSemantic(Initializer init, Scope* sc, ref Typ return i; } + Initializer visitDefault(DefaultInitializer i) + { + i.type = t; + return i; + } + Initializer visitError(ErrorInitializer i) { return i; @@ -1017,6 +1024,12 @@ Initializer inferType(Initializer init, Scope* sc) return new ErrorInitializer(); } + Initializer visitDefault(DefaultInitializer i) + { + error(i.loc, "cannot infer type from default initializer"); + return new ErrorInitializer(); + } + Initializer visitError(ErrorInitializer i) { return i; @@ -1175,6 +1188,11 @@ extern (C++) Expression initializerToExpression(Initializer init, Type itype = n return null; } + Expression visitDefault(DefaultInitializer di) + { + return di.type ? di.type.defaultInit(Loc.initial, isCfile) : null; + } + Expression visitError(ErrorInitializer) { return ErrorExp.get(); diff --git a/dmd/parsetimevisitor.d b/dmd/parsetimevisitor.d index a4a9434334e..3d0a5854625 100644 --- a/dmd/parsetimevisitor.d +++ b/dmd/parsetimevisitor.d @@ -298,5 +298,6 @@ public: void visit(AST.StructInitializer i) { visit(cast(AST.Initializer)i); } void visit(AST.ArrayInitializer i) { visit(cast(AST.Initializer)i); } void visit(AST.VoidInitializer i) { visit(cast(AST.Initializer)i); } + void visit(AST.DefaultInitializer i) { visit(cast(AST.Initializer)i); } void visit(AST.CInitializer i) { visit(cast(AST.CInitializer)i); } } diff --git a/dmd/strictvisitor.d b/dmd/strictvisitor.d index 82e91c6aa76..39fcb68f0b8 100644 --- a/dmd/strictvisitor.d +++ b/dmd/strictvisitor.d @@ -234,5 +234,6 @@ extern(C++) class StrictVisitor(AST) : ParseTimeVisitor!AST override void visit(AST.StructInitializer) { assert(0); } override void visit(AST.ArrayInitializer) { assert(0); } override void visit(AST.VoidInitializer) { assert(0); } + override void visit(AST.DefaultInitializer) { assert(0); } override void visit(AST.CInitializer) { assert(0); } } diff --git a/dmd/visitor.h b/dmd/visitor.h index 3d8c3e60220..360784a1076 100644 --- a/dmd/visitor.h +++ b/dmd/visitor.h @@ -176,6 +176,7 @@ class NewDeclaration; class Initializer; class VoidInitializer; +class DefaultInitializer; class ErrorInitializer; class StructInitializer; class ArrayInitializer; @@ -591,6 +592,7 @@ class ParseTimeVisitor virtual void visit(StructInitializer *i) { visit((Initializer *)i); } virtual void visit(ArrayInitializer *i) { visit((Initializer *)i); } virtual void visit(VoidInitializer *i) { visit((Initializer *)i); } + virtual void visit(DefaultInitializer *i) { visit((Initializer *)i); } virtual void visit(CInitializer *i) { visit((Initializer *)i); } }; diff --git a/tests/dmd/runnable/initializer.c b/tests/dmd/runnable/initializer.c index a7abdd07c24..805b855207e 100644 --- a/tests/dmd/runnable/initializer.c +++ b/tests/dmd/runnable/initializer.c @@ -844,6 +844,30 @@ void test24154() /*******************************************/ +// https://issues.dlang.org/show_bug.cgi?id=24155 + +struct S24155 { int x, y; }; + +struct S24155 s = { }; + +void abc(int i) +{ + assert(s.x == 0 && s.y == 0, __LINE__); + struct S24155 s1 = { }; + assert(s1.x == 0 && s1.y == 0, __LINE__); + struct S24155 s2 = { { i }, { } }; + assert(s2.x == i && s2.y == 0, __LINE__); + struct S24155 s3 = { { }, { i } }; + assert(s3.x == 0 && s3.y == i, __LINE__); +} + +void test24155() +{ + abc(1); +} + +/*******************************************/ + int main() { test1(); @@ -893,6 +917,7 @@ int main() test22925(); test47(); test24154(); + test24155(); return 0; } From e664017e6d0bbcac11e2f8a8c69b2c38ecf8229d Mon Sep 17 00:00:00 2001 From: Walter Bright Date: Wed, 15 Nov 2023 21:51:35 -0800 Subject: [PATCH 039/215] dmd inline assembler supports PAUSE instruction --- runtime/druntime/src/core/internal/atomic.d | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/runtime/druntime/src/core/internal/atomic.d b/runtime/druntime/src/core/internal/atomic.d index 5daab89a387..eebf94ee29d 100644 --- a/runtime/druntime/src/core/internal/atomic.d +++ b/runtime/druntime/src/core/internal/atomic.d @@ -656,7 +656,7 @@ version (DigitalMars) asm pure nothrow @nogc @trusted { naked; - rep; nop; + pause; ret; } } @@ -665,8 +665,7 @@ version (DigitalMars) asm pure nothrow @nogc @trusted { naked; - // pause; // TODO: DMD should add this opcode to its inline asm - rep; nop; + pause; ret; } } From d93fd5e29ff66878348726a12fc614b85bbf8329 Mon Sep 17 00:00:00 2001 From: Dennis Date: Thu, 16 Nov 2023 11:23:45 +0100 Subject: [PATCH 040/215] Fix 20332 - associative array clear function should be @safe (dlang/dmd!15817) --- runtime/druntime/src/object.d | 6 +++--- runtime/druntime/src/rt/aaA.d | 8 ++++---- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/runtime/druntime/src/object.d b/runtime/druntime/src/object.d index 0111be0b617..c6e0fc45d63 100644 --- a/runtime/druntime/src/object.d +++ b/runtime/druntime/src/object.d @@ -2918,19 +2918,19 @@ alias AssociativeArray(Key, Value) = Value[Key]; * Params: * aa = The associative array. */ -void clear(Value, Key)(Value[Key] aa) +void clear(Value, Key)(Value[Key] aa) @trusted { _aaClear(*cast(AA *) &aa); } /** ditto */ -void clear(Value, Key)(Value[Key]* aa) +void clear(Value, Key)(Value[Key]* aa) @trusted { _aaClear(*cast(AA *) aa); } /// -@system unittest +@safe unittest { auto aa = ["k1": 2]; aa.clear; diff --git a/runtime/druntime/src/rt/aaA.d b/runtime/druntime/src/rt/aaA.d index 4014862b4e4..978f8346512 100644 --- a/runtime/druntime/src/rt/aaA.d +++ b/runtime/druntime/src/rt/aaA.d @@ -41,7 +41,7 @@ struct AA Impl* impl; alias impl this; - private @property bool empty() const pure nothrow @nogc + private @property bool empty() const pure nothrow @nogc @safe { return impl is null || !impl.length; } @@ -85,7 +85,7 @@ private: hasPointers = 0x2, } - @property size_t length() const pure nothrow @nogc + @property size_t length() const pure nothrow @nogc @safe { assert(used >= deleted); return used - deleted; @@ -156,7 +156,7 @@ private: GC.free(obuckets.ptr); // safe to free b/c impossible to reference } - void clear() pure nothrow + void clear() pure nothrow @trusted { import core.stdc.string : memset; // clear all data, but don't change bucket array length @@ -648,7 +648,7 @@ extern (C) bool _aaDelX(AA aa, scope const TypeInfo keyti, scope const void* pke } /// Remove all elements from AA. -extern (C) void _aaClear(AA aa) pure nothrow +extern (C) void _aaClear(AA aa) pure nothrow @safe { if (!aa.empty) { From 1e3531d2a8df12cab8f2ae5fd67037f673c1ea22 Mon Sep 17 00:00:00 2001 From: Martin Kinkelin Date: Thu, 16 Nov 2023 11:40:26 +0100 Subject: [PATCH 041/215] VSOptions: Prepare for setting the INCLUDE env var for importC (dlang/dmd!15780) Upstreaming from LDC, to pave the way for fixing Issue 24111. --- dmd/vsoptions.d | 36 ++++++++++++++++++++++++++++++++++++ dmd/vsoptions.h | 2 ++ 2 files changed, 38 insertions(+) diff --git a/dmd/vsoptions.d b/dmd/vsoptions.d index d735040c1b6..be8f735c605 100644 --- a/dmd/vsoptions.d +++ b/dmd/vsoptions.d @@ -471,6 +471,18 @@ public: return FileName.exists(proposed) ? proposed : null; } + const(char)* getVCIncludeDir() const + { + const(char)* proposed; + + if (VCToolsInstallDir !is null) + proposed = FileName.combine(VCToolsInstallDir, "include"); + else if (VCInstallDir !is null) + proposed = FileName.combine(VCInstallDir, "include"); + + return FileName.exists(proposed) ? proposed : null; + } + /** * get the path to the universal CRT libraries * Params: @@ -528,6 +540,30 @@ public: return null; } + const(char)* getSDKIncludePath() const + { + if (WindowsSdkDir) + { + alias umExists = returnDirIfContainsFile!"um"; // subdir in this case + + const sdk = FileName.combine(WindowsSdkDir.toDString, "include"); + if (WindowsSdkVersion) + { + if (auto p = umExists(sdk, WindowsSdkVersion.toDString)) // SDK 10.0 + return p; + } + // purely speculative + if (auto p = umExists(sdk, "win8")) // SDK 8.0 + return p; + if (auto p = umExists(sdk, "winv6.3")) // SDK 8.1 + return p; + if (auto p = umExists(sdk)) // SDK 7.1 or earlier + return p; + } + + return null; + } + private: extern(D): diff --git a/dmd/vsoptions.h b/dmd/vsoptions.h index fc63e1c1b9b..5c6a7c38257 100644 --- a/dmd/vsoptions.h +++ b/dmd/vsoptions.h @@ -25,8 +25,10 @@ struct VSOptions void initialize(); const char *getVCBinDir(bool x64, const char *&addpath) const; const char *getVCLibDir(bool x64) const; + const char *getVCIncludeDir() const; const char *getUCRTLibPath(bool x64) const; const char *getSDKLibPath(bool x64) const; + const char *getSDKIncludePath() const; }; #endif // _WIN32 From 45065d117fc35d120823208104c83d7a5c911dbb Mon Sep 17 00:00:00 2001 From: Nick Treleaven Date: Thu, 16 Nov 2023 15:50:58 +0000 Subject: [PATCH 042/215] Improve 'not callable using a $mod object' error Change to 'cannot construct a $mod object' for constructor calls. Add message showing `fd.loc` with params + mod. --- dmd/func.d | 14 ++-- tests/dmd/fail_compilation/diag1730.d | 92 ++++++++++++++++---------- tests/dmd/fail_compilation/diag6707.d | 5 +- tests/dmd/fail_compilation/diag8101b.d | 21 +++--- tests/dmd/fail_compilation/fail217.d | 5 +- tests/dmd/fail_compilation/fail241.d | 10 +-- tests/dmd/fail_compilation/ice9759.d | 5 +- 7 files changed, 93 insertions(+), 59 deletions(-) diff --git a/dmd/func.d b/dmd/func.d index edf113e2160..e53144f9120 100644 --- a/dmd/func.d +++ b/dmd/func.d @@ -3447,13 +3447,19 @@ FuncDeclaration resolveFuncCall(const ref Loc loc, Scope* sc, Dsymbol s, return null; } - .error(loc, "%smethod `%s` is not callable using a %sobject", - funcBuf.peekChars(), fd.toPrettyChars(), thisBuf.peekChars()); + if (fd.isCtorDeclaration()) + .error(loc, "%s%s `%s` cannot construct a %sobject", + funcBuf.peekChars(), fd.kind(), fd.toChars(), thisBuf.peekChars()); + else + .error(loc, "%smethod `%s` is not callable using a %sobject", + funcBuf.peekChars(), fd.toChars(), thisBuf.peekChars()); + .errorSupplemental(fd.loc, "`%s%s%s` declared here", + fd.toPrettyChars(), parametersTypeToChars(tf.parameterList), tf.modToChars()); if (mismatches.isNotShared) - .errorSupplemental(fd.loc, "Consider adding `shared` here"); + .errorSupplemental(fd.loc, "Consider adding `shared`"); else if (mismatches.isMutable) - .errorSupplemental(fd.loc, "Consider adding `const` or `inout` here"); + .errorSupplemental(fd.loc, "Consider adding `const` or `inout`"); return null; } diff --git a/tests/dmd/fail_compilation/diag1730.d b/tests/dmd/fail_compilation/diag1730.d index 0ab51422ba1..e40f9e168e7 100644 --- a/tests/dmd/fail_compilation/diag1730.d +++ b/tests/dmd/fail_compilation/diag1730.d @@ -1,41 +1,63 @@ /* TEST_OUTPUT: --- -fail_compilation/diag1730.d(51): Error: mutable method `diag1730.S.func` is not callable using a `inout` object -fail_compilation/diag1730.d(43): Consider adding `const` or `inout` here -fail_compilation/diag1730.d(53): Error: `immutable` method `diag1730.S.iFunc` is not callable using a `inout` object -fail_compilation/diag1730.d(54): Error: `shared` mutable method `diag1730.S.sFunc` is not callable using a non-shared `inout` object -fail_compilation/diag1730.d(46): Consider adding `const` or `inout` here -fail_compilation/diag1730.d(55): Error: `shared` `const` method `diag1730.S.scFunc` is not callable using a non-shared `inout` object -fail_compilation/diag1730.d(70): Error: `immutable` method `diag1730.S.iFunc` is not callable using a mutable object -fail_compilation/diag1730.d(71): Error: `shared` method `diag1730.S.sFunc` is not callable using a non-shared object -fail_compilation/diag1730.d(72): Error: `shared` `const` method `diag1730.S.scFunc` is not callable using a non-shared mutable object -fail_compilation/diag1730.d(75): Error: mutable method `diag1730.S.func` is not callable using a `const` object -fail_compilation/diag1730.d(43): Consider adding `const` or `inout` here -fail_compilation/diag1730.d(77): Error: `immutable` method `diag1730.S.iFunc` is not callable using a `const` object -fail_compilation/diag1730.d(78): Error: `shared` mutable method `diag1730.S.sFunc` is not callable using a non-shared `const` object -fail_compilation/diag1730.d(46): Consider adding `const` or `inout` here -fail_compilation/diag1730.d(79): Error: `shared` `const` method `diag1730.S.scFunc` is not callable using a non-shared `const` object -fail_compilation/diag1730.d(82): Error: mutable method `diag1730.S.func` is not callable using a `immutable` object -fail_compilation/diag1730.d(43): Consider adding `const` or `inout` here -fail_compilation/diag1730.d(85): Error: `shared` mutable method `diag1730.S.sFunc` is not callable using a `immutable` object -fail_compilation/diag1730.d(46): Consider adding `const` or `inout` here -fail_compilation/diag1730.d(89): Error: non-shared method `diag1730.S.func` is not callable using a `shared` object -fail_compilation/diag1730.d(43): Consider adding `shared` here -fail_compilation/diag1730.d(90): Error: non-shared `const` method `diag1730.S.cFunc` is not callable using a `shared` mutable object -fail_compilation/diag1730.d(44): Consider adding `shared` here -fail_compilation/diag1730.d(91): Error: `immutable` method `diag1730.S.iFunc` is not callable using a `shared` mutable object -fail_compilation/diag1730.d(94): Error: non-shared `inout` method `diag1730.S.wFunc` is not callable using a `shared` mutable object -fail_compilation/diag1730.d(48): Consider adding `shared` here -fail_compilation/diag1730.d(96): Error: non-shared mutable method `diag1730.S.func` is not callable using a `shared` `const` object -fail_compilation/diag1730.d(43): Consider adding `shared` here -fail_compilation/diag1730.d(97): Error: non-shared `const` method `diag1730.S.cFunc` is not callable using a `shared` `const` object -fail_compilation/diag1730.d(44): Consider adding `shared` here -fail_compilation/diag1730.d(98): Error: `immutable` method `diag1730.S.iFunc` is not callable using a `shared` `const` object -fail_compilation/diag1730.d(99): Error: `shared` mutable method `diag1730.S.sFunc` is not callable using a `shared` `const` object -fail_compilation/diag1730.d(46): Consider adding `const` or `inout` here -fail_compilation/diag1730.d(101): Error: non-shared `inout` method `diag1730.S.wFunc` is not callable using a `shared` `const` object -fail_compilation/diag1730.d(48): Consider adding `shared` here +fail_compilation/diag1730.d(73): Error: mutable method `func` is not callable using a `inout` object +fail_compilation/diag1730.d(65): `diag1730.S.func()` declared here +fail_compilation/diag1730.d(65): Consider adding `const` or `inout` +fail_compilation/diag1730.d(75): Error: `immutable` method `iFunc` is not callable using a `inout` object +fail_compilation/diag1730.d(67): `diag1730.S.iFunc() immutable` declared here +fail_compilation/diag1730.d(76): Error: `shared` mutable method `sFunc` is not callable using a non-shared `inout` object +fail_compilation/diag1730.d(68): `diag1730.S.sFunc() shared` declared here +fail_compilation/diag1730.d(68): Consider adding `const` or `inout` +fail_compilation/diag1730.d(77): Error: `shared` `const` method `scFunc` is not callable using a non-shared `inout` object +fail_compilation/diag1730.d(69): `diag1730.S.scFunc() shared const` declared here +fail_compilation/diag1730.d(92): Error: `immutable` method `iFunc` is not callable using a mutable object +fail_compilation/diag1730.d(67): `diag1730.S.iFunc() immutable` declared here +fail_compilation/diag1730.d(93): Error: `shared` method `sFunc` is not callable using a non-shared object +fail_compilation/diag1730.d(68): `diag1730.S.sFunc() shared` declared here +fail_compilation/diag1730.d(94): Error: `shared` `const` method `scFunc` is not callable using a non-shared mutable object +fail_compilation/diag1730.d(69): `diag1730.S.scFunc() shared const` declared here +fail_compilation/diag1730.d(97): Error: mutable method `func` is not callable using a `const` object +fail_compilation/diag1730.d(65): `diag1730.S.func()` declared here +fail_compilation/diag1730.d(65): Consider adding `const` or `inout` +fail_compilation/diag1730.d(99): Error: `immutable` method `iFunc` is not callable using a `const` object +fail_compilation/diag1730.d(67): `diag1730.S.iFunc() immutable` declared here +fail_compilation/diag1730.d(100): Error: `shared` mutable method `sFunc` is not callable using a non-shared `const` object +fail_compilation/diag1730.d(68): `diag1730.S.sFunc() shared` declared here +fail_compilation/diag1730.d(68): Consider adding `const` or `inout` +fail_compilation/diag1730.d(101): Error: `shared` `const` method `scFunc` is not callable using a non-shared `const` object +fail_compilation/diag1730.d(69): `diag1730.S.scFunc() shared const` declared here +fail_compilation/diag1730.d(104): Error: mutable method `func` is not callable using a `immutable` object +fail_compilation/diag1730.d(65): `diag1730.S.func()` declared here +fail_compilation/diag1730.d(65): Consider adding `const` or `inout` +fail_compilation/diag1730.d(107): Error: `shared` mutable method `sFunc` is not callable using a `immutable` object +fail_compilation/diag1730.d(68): `diag1730.S.sFunc() shared` declared here +fail_compilation/diag1730.d(68): Consider adding `const` or `inout` +fail_compilation/diag1730.d(111): Error: non-shared method `func` is not callable using a `shared` object +fail_compilation/diag1730.d(65): `diag1730.S.func()` declared here +fail_compilation/diag1730.d(65): Consider adding `shared` +fail_compilation/diag1730.d(112): Error: non-shared `const` method `cFunc` is not callable using a `shared` mutable object +fail_compilation/diag1730.d(66): `diag1730.S.cFunc() const` declared here +fail_compilation/diag1730.d(66): Consider adding `shared` +fail_compilation/diag1730.d(113): Error: `immutable` method `iFunc` is not callable using a `shared` mutable object +fail_compilation/diag1730.d(67): `diag1730.S.iFunc() immutable` declared here +fail_compilation/diag1730.d(116): Error: non-shared `inout` method `wFunc` is not callable using a `shared` mutable object +fail_compilation/diag1730.d(70): `diag1730.S.wFunc() inout` declared here +fail_compilation/diag1730.d(70): Consider adding `shared` +fail_compilation/diag1730.d(118): Error: non-shared mutable method `func` is not callable using a `shared` `const` object +fail_compilation/diag1730.d(65): `diag1730.S.func()` declared here +fail_compilation/diag1730.d(65): Consider adding `shared` +fail_compilation/diag1730.d(119): Error: non-shared `const` method `cFunc` is not callable using a `shared` `const` object +fail_compilation/diag1730.d(66): `diag1730.S.cFunc() const` declared here +fail_compilation/diag1730.d(66): Consider adding `shared` +fail_compilation/diag1730.d(120): Error: `immutable` method `iFunc` is not callable using a `shared` `const` object +fail_compilation/diag1730.d(67): `diag1730.S.iFunc() immutable` declared here +fail_compilation/diag1730.d(121): Error: `shared` mutable method `sFunc` is not callable using a `shared` `const` object +fail_compilation/diag1730.d(68): `diag1730.S.sFunc() shared` declared here +fail_compilation/diag1730.d(68): Consider adding `const` or `inout` +fail_compilation/diag1730.d(123): Error: non-shared `inout` method `wFunc` is not callable using a `shared` `const` object +fail_compilation/diag1730.d(70): `diag1730.S.wFunc() inout` declared here +fail_compilation/diag1730.d(70): Consider adding `shared` --- */ struct S diff --git a/tests/dmd/fail_compilation/diag6707.d b/tests/dmd/fail_compilation/diag6707.d index 70fea4fcf68..c584a3bc41d 100644 --- a/tests/dmd/fail_compilation/diag6707.d +++ b/tests/dmd/fail_compilation/diag6707.d @@ -1,8 +1,9 @@ /* TEST_OUTPUT: --- -fail_compilation/diag6707.d(17): Error: mutable method `diag6707.Foo.value` is not callable using a `const` object -fail_compilation/diag6707.d(13): Consider adding `const` or `inout` here +fail_compilation/diag6707.d(18): Error: mutable method `value` is not callable using a `const` object +fail_compilation/diag6707.d(14): `diag6707.Foo.value()` declared here +fail_compilation/diag6707.d(14): Consider adding `const` or `inout` --- */ diff --git a/tests/dmd/fail_compilation/diag8101b.d b/tests/dmd/fail_compilation/diag8101b.d index a55ef731ad2..b1e168df498 100644 --- a/tests/dmd/fail_compilation/diag8101b.d +++ b/tests/dmd/fail_compilation/diag8101b.d @@ -1,16 +1,17 @@ /* TEST_OUTPUT: --- -fail_compilation/diag8101b.d(28): Error: none of the overloads of `foo` are callable using argument types `(double)` -fail_compilation/diag8101b.d(19): Candidates are: `diag8101b.S.foo(int __param_0)` -fail_compilation/diag8101b.d(20): `diag8101b.S.foo(int __param_0, int __param_1)` -fail_compilation/diag8101b.d(30): Error: function `diag8101b.S.bar(int __param_0)` is not callable using argument types `(double)` -fail_compilation/diag8101b.d(30): cannot pass argument `1.0` of type `double` to parameter `int __param_0` -fail_compilation/diag8101b.d(33): Error: none of the overloads of `foo` are callable using a `const` object -fail_compilation/diag8101b.d(19): Candidates are: `diag8101b.S.foo(int __param_0)` -fail_compilation/diag8101b.d(20): `diag8101b.S.foo(int __param_0, int __param_1)` -fail_compilation/diag8101b.d(35): Error: mutable method `diag8101b.S.bar` is not callable using a `const` object -fail_compilation/diag8101b.d(22): Consider adding `const` or `inout` here +fail_compilation/diag8101b.d(29): Error: none of the overloads of `foo` are callable using argument types `(double)` +fail_compilation/diag8101b.d(20): Candidates are: `diag8101b.S.foo(int __param_0)` +fail_compilation/diag8101b.d(21): `diag8101b.S.foo(int __param_0, int __param_1)` +fail_compilation/diag8101b.d(31): Error: function `diag8101b.S.bar(int __param_0)` is not callable using argument types `(double)` +fail_compilation/diag8101b.d(31): cannot pass argument `1.0` of type `double` to parameter `int __param_0` +fail_compilation/diag8101b.d(34): Error: none of the overloads of `foo` are callable using a `const` object +fail_compilation/diag8101b.d(20): Candidates are: `diag8101b.S.foo(int __param_0)` +fail_compilation/diag8101b.d(21): `diag8101b.S.foo(int __param_0, int __param_1)` +fail_compilation/diag8101b.d(36): Error: mutable method `bar` is not callable using a `const` object +fail_compilation/diag8101b.d(23): `diag8101b.S.bar(int __param_0)` declared here +fail_compilation/diag8101b.d(23): Consider adding `const` or `inout` --- */ diff --git a/tests/dmd/fail_compilation/fail217.d b/tests/dmd/fail_compilation/fail217.d index 11ad76fabdc..723e77ccf63 100644 --- a/tests/dmd/fail_compilation/fail217.d +++ b/tests/dmd/fail_compilation/fail217.d @@ -1,8 +1,9 @@ /* TEST_OUTPUT: --- -fail_compilation/fail217.d(22): Error: mutable method `fail217.Message.this` is not callable using a `immutable` object -fail_compilation/fail217.d(13): Consider adding `const` or `inout` here +fail_compilation/fail217.d(23): Error: mutable constructor `this` cannot construct a `immutable` object +fail_compilation/fail217.d(14): `fail217.Message.this(int notifier_object)` declared here +fail_compilation/fail217.d(14): Consider adding `const` or `inout` --- */ diff --git a/tests/dmd/fail_compilation/fail241.d b/tests/dmd/fail_compilation/fail241.d index babd193033b..0475f240367 100644 --- a/tests/dmd/fail_compilation/fail241.d +++ b/tests/dmd/fail_compilation/fail241.d @@ -1,10 +1,12 @@ /* TEST_OUTPUT: --- -fail_compilation/fail241.d(18): Error: mutable method `fail241.Foo.f` is not callable using a `const` object -fail_compilation/fail241.d(13): Consider adding `const` or `inout` here -fail_compilation/fail241.d(19): Error: mutable method `fail241.Foo.g` is not callable using a `const` object -fail_compilation/fail241.d(14): Consider adding `const` or `inout` here +fail_compilation/fail241.d(20): Error: mutable method `f` is not callable using a `const` object +fail_compilation/fail241.d(15): `fail241.Foo.f()` declared here +fail_compilation/fail241.d(15): Consider adding `const` or `inout` +fail_compilation/fail241.d(21): Error: mutable method `g` is not callable using a `const` object +fail_compilation/fail241.d(16): `fail241.Foo.g()` declared here +fail_compilation/fail241.d(16): Consider adding `const` or `inout` --- */ diff --git a/tests/dmd/fail_compilation/ice9759.d b/tests/dmd/fail_compilation/ice9759.d index 6608b58fc0b..398478fe4d9 100644 --- a/tests/dmd/fail_compilation/ice9759.d +++ b/tests/dmd/fail_compilation/ice9759.d @@ -1,8 +1,9 @@ /* TEST_OUTPUT: --- -fail_compilation/ice9759.d(25): Error: mutable method `ice9759.Json.opAssign` is not callable using a `const` object -fail_compilation/ice9759.d(17): Consider adding `const` or `inout` here +fail_compilation/ice9759.d(26): Error: mutable method `opAssign` is not callable using a `const` object +fail_compilation/ice9759.d(18): `ice9759.Json.opAssign(Json v)` declared here +fail_compilation/ice9759.d(18): Consider adding `const` or `inout` --- */ From b3c6aab0a9b936e2fd7bb0a3d024bec650e895e7 Mon Sep 17 00:00:00 2001 From: Nick Treleaven Date: Thu, 16 Nov 2023 16:07:23 +0000 Subject: [PATCH 043/215] Postpone minor changes --- dmd/func.d | 10 ++- tests/dmd/fail_compilation/diag1730.d | 92 ++++++++++---------------- tests/dmd/fail_compilation/diag6707.d | 5 +- tests/dmd/fail_compilation/diag8101b.d | 21 +++--- tests/dmd/fail_compilation/fail217.d | 5 +- tests/dmd/fail_compilation/fail241.d | 10 ++- tests/dmd/fail_compilation/ice9759.d | 5 +- 7 files changed, 59 insertions(+), 89 deletions(-) diff --git a/dmd/func.d b/dmd/func.d index e53144f9120..bbe80a27db9 100644 --- a/dmd/func.d +++ b/dmd/func.d @@ -3449,17 +3449,15 @@ FuncDeclaration resolveFuncCall(const ref Loc loc, Scope* sc, Dsymbol s, if (fd.isCtorDeclaration()) .error(loc, "%s%s `%s` cannot construct a %sobject", - funcBuf.peekChars(), fd.kind(), fd.toChars(), thisBuf.peekChars()); + funcBuf.peekChars(), fd.kind(), fd.toPrettyChars(), thisBuf.peekChars()); else .error(loc, "%smethod `%s` is not callable using a %sobject", - funcBuf.peekChars(), fd.toChars(), thisBuf.peekChars()); - .errorSupplemental(fd.loc, "`%s%s%s` declared here", - fd.toPrettyChars(), parametersTypeToChars(tf.parameterList), tf.modToChars()); + funcBuf.peekChars(), fd.toPrettyChars(), thisBuf.peekChars()); if (mismatches.isNotShared) - .errorSupplemental(fd.loc, "Consider adding `shared`"); + .errorSupplemental(fd.loc, "Consider adding `shared` here"); else if (mismatches.isMutable) - .errorSupplemental(fd.loc, "Consider adding `const` or `inout`"); + .errorSupplemental(fd.loc, "Consider adding `const` or `inout` here"); return null; } diff --git a/tests/dmd/fail_compilation/diag1730.d b/tests/dmd/fail_compilation/diag1730.d index e40f9e168e7..0ab51422ba1 100644 --- a/tests/dmd/fail_compilation/diag1730.d +++ b/tests/dmd/fail_compilation/diag1730.d @@ -1,63 +1,41 @@ /* TEST_OUTPUT: --- -fail_compilation/diag1730.d(73): Error: mutable method `func` is not callable using a `inout` object -fail_compilation/diag1730.d(65): `diag1730.S.func()` declared here -fail_compilation/diag1730.d(65): Consider adding `const` or `inout` -fail_compilation/diag1730.d(75): Error: `immutable` method `iFunc` is not callable using a `inout` object -fail_compilation/diag1730.d(67): `diag1730.S.iFunc() immutable` declared here -fail_compilation/diag1730.d(76): Error: `shared` mutable method `sFunc` is not callable using a non-shared `inout` object -fail_compilation/diag1730.d(68): `diag1730.S.sFunc() shared` declared here -fail_compilation/diag1730.d(68): Consider adding `const` or `inout` -fail_compilation/diag1730.d(77): Error: `shared` `const` method `scFunc` is not callable using a non-shared `inout` object -fail_compilation/diag1730.d(69): `diag1730.S.scFunc() shared const` declared here -fail_compilation/diag1730.d(92): Error: `immutable` method `iFunc` is not callable using a mutable object -fail_compilation/diag1730.d(67): `diag1730.S.iFunc() immutable` declared here -fail_compilation/diag1730.d(93): Error: `shared` method `sFunc` is not callable using a non-shared object -fail_compilation/diag1730.d(68): `diag1730.S.sFunc() shared` declared here -fail_compilation/diag1730.d(94): Error: `shared` `const` method `scFunc` is not callable using a non-shared mutable object -fail_compilation/diag1730.d(69): `diag1730.S.scFunc() shared const` declared here -fail_compilation/diag1730.d(97): Error: mutable method `func` is not callable using a `const` object -fail_compilation/diag1730.d(65): `diag1730.S.func()` declared here -fail_compilation/diag1730.d(65): Consider adding `const` or `inout` -fail_compilation/diag1730.d(99): Error: `immutable` method `iFunc` is not callable using a `const` object -fail_compilation/diag1730.d(67): `diag1730.S.iFunc() immutable` declared here -fail_compilation/diag1730.d(100): Error: `shared` mutable method `sFunc` is not callable using a non-shared `const` object -fail_compilation/diag1730.d(68): `diag1730.S.sFunc() shared` declared here -fail_compilation/diag1730.d(68): Consider adding `const` or `inout` -fail_compilation/diag1730.d(101): Error: `shared` `const` method `scFunc` is not callable using a non-shared `const` object -fail_compilation/diag1730.d(69): `diag1730.S.scFunc() shared const` declared here -fail_compilation/diag1730.d(104): Error: mutable method `func` is not callable using a `immutable` object -fail_compilation/diag1730.d(65): `diag1730.S.func()` declared here -fail_compilation/diag1730.d(65): Consider adding `const` or `inout` -fail_compilation/diag1730.d(107): Error: `shared` mutable method `sFunc` is not callable using a `immutable` object -fail_compilation/diag1730.d(68): `diag1730.S.sFunc() shared` declared here -fail_compilation/diag1730.d(68): Consider adding `const` or `inout` -fail_compilation/diag1730.d(111): Error: non-shared method `func` is not callable using a `shared` object -fail_compilation/diag1730.d(65): `diag1730.S.func()` declared here -fail_compilation/diag1730.d(65): Consider adding `shared` -fail_compilation/diag1730.d(112): Error: non-shared `const` method `cFunc` is not callable using a `shared` mutable object -fail_compilation/diag1730.d(66): `diag1730.S.cFunc() const` declared here -fail_compilation/diag1730.d(66): Consider adding `shared` -fail_compilation/diag1730.d(113): Error: `immutable` method `iFunc` is not callable using a `shared` mutable object -fail_compilation/diag1730.d(67): `diag1730.S.iFunc() immutable` declared here -fail_compilation/diag1730.d(116): Error: non-shared `inout` method `wFunc` is not callable using a `shared` mutable object -fail_compilation/diag1730.d(70): `diag1730.S.wFunc() inout` declared here -fail_compilation/diag1730.d(70): Consider adding `shared` -fail_compilation/diag1730.d(118): Error: non-shared mutable method `func` is not callable using a `shared` `const` object -fail_compilation/diag1730.d(65): `diag1730.S.func()` declared here -fail_compilation/diag1730.d(65): Consider adding `shared` -fail_compilation/diag1730.d(119): Error: non-shared `const` method `cFunc` is not callable using a `shared` `const` object -fail_compilation/diag1730.d(66): `diag1730.S.cFunc() const` declared here -fail_compilation/diag1730.d(66): Consider adding `shared` -fail_compilation/diag1730.d(120): Error: `immutable` method `iFunc` is not callable using a `shared` `const` object -fail_compilation/diag1730.d(67): `diag1730.S.iFunc() immutable` declared here -fail_compilation/diag1730.d(121): Error: `shared` mutable method `sFunc` is not callable using a `shared` `const` object -fail_compilation/diag1730.d(68): `diag1730.S.sFunc() shared` declared here -fail_compilation/diag1730.d(68): Consider adding `const` or `inout` -fail_compilation/diag1730.d(123): Error: non-shared `inout` method `wFunc` is not callable using a `shared` `const` object -fail_compilation/diag1730.d(70): `diag1730.S.wFunc() inout` declared here -fail_compilation/diag1730.d(70): Consider adding `shared` +fail_compilation/diag1730.d(51): Error: mutable method `diag1730.S.func` is not callable using a `inout` object +fail_compilation/diag1730.d(43): Consider adding `const` or `inout` here +fail_compilation/diag1730.d(53): Error: `immutable` method `diag1730.S.iFunc` is not callable using a `inout` object +fail_compilation/diag1730.d(54): Error: `shared` mutable method `diag1730.S.sFunc` is not callable using a non-shared `inout` object +fail_compilation/diag1730.d(46): Consider adding `const` or `inout` here +fail_compilation/diag1730.d(55): Error: `shared` `const` method `diag1730.S.scFunc` is not callable using a non-shared `inout` object +fail_compilation/diag1730.d(70): Error: `immutable` method `diag1730.S.iFunc` is not callable using a mutable object +fail_compilation/diag1730.d(71): Error: `shared` method `diag1730.S.sFunc` is not callable using a non-shared object +fail_compilation/diag1730.d(72): Error: `shared` `const` method `diag1730.S.scFunc` is not callable using a non-shared mutable object +fail_compilation/diag1730.d(75): Error: mutable method `diag1730.S.func` is not callable using a `const` object +fail_compilation/diag1730.d(43): Consider adding `const` or `inout` here +fail_compilation/diag1730.d(77): Error: `immutable` method `diag1730.S.iFunc` is not callable using a `const` object +fail_compilation/diag1730.d(78): Error: `shared` mutable method `diag1730.S.sFunc` is not callable using a non-shared `const` object +fail_compilation/diag1730.d(46): Consider adding `const` or `inout` here +fail_compilation/diag1730.d(79): Error: `shared` `const` method `diag1730.S.scFunc` is not callable using a non-shared `const` object +fail_compilation/diag1730.d(82): Error: mutable method `diag1730.S.func` is not callable using a `immutable` object +fail_compilation/diag1730.d(43): Consider adding `const` or `inout` here +fail_compilation/diag1730.d(85): Error: `shared` mutable method `diag1730.S.sFunc` is not callable using a `immutable` object +fail_compilation/diag1730.d(46): Consider adding `const` or `inout` here +fail_compilation/diag1730.d(89): Error: non-shared method `diag1730.S.func` is not callable using a `shared` object +fail_compilation/diag1730.d(43): Consider adding `shared` here +fail_compilation/diag1730.d(90): Error: non-shared `const` method `diag1730.S.cFunc` is not callable using a `shared` mutable object +fail_compilation/diag1730.d(44): Consider adding `shared` here +fail_compilation/diag1730.d(91): Error: `immutable` method `diag1730.S.iFunc` is not callable using a `shared` mutable object +fail_compilation/diag1730.d(94): Error: non-shared `inout` method `diag1730.S.wFunc` is not callable using a `shared` mutable object +fail_compilation/diag1730.d(48): Consider adding `shared` here +fail_compilation/diag1730.d(96): Error: non-shared mutable method `diag1730.S.func` is not callable using a `shared` `const` object +fail_compilation/diag1730.d(43): Consider adding `shared` here +fail_compilation/diag1730.d(97): Error: non-shared `const` method `diag1730.S.cFunc` is not callable using a `shared` `const` object +fail_compilation/diag1730.d(44): Consider adding `shared` here +fail_compilation/diag1730.d(98): Error: `immutable` method `diag1730.S.iFunc` is not callable using a `shared` `const` object +fail_compilation/diag1730.d(99): Error: `shared` mutable method `diag1730.S.sFunc` is not callable using a `shared` `const` object +fail_compilation/diag1730.d(46): Consider adding `const` or `inout` here +fail_compilation/diag1730.d(101): Error: non-shared `inout` method `diag1730.S.wFunc` is not callable using a `shared` `const` object +fail_compilation/diag1730.d(48): Consider adding `shared` here --- */ struct S diff --git a/tests/dmd/fail_compilation/diag6707.d b/tests/dmd/fail_compilation/diag6707.d index c584a3bc41d..70fea4fcf68 100644 --- a/tests/dmd/fail_compilation/diag6707.d +++ b/tests/dmd/fail_compilation/diag6707.d @@ -1,9 +1,8 @@ /* TEST_OUTPUT: --- -fail_compilation/diag6707.d(18): Error: mutable method `value` is not callable using a `const` object -fail_compilation/diag6707.d(14): `diag6707.Foo.value()` declared here -fail_compilation/diag6707.d(14): Consider adding `const` or `inout` +fail_compilation/diag6707.d(17): Error: mutable method `diag6707.Foo.value` is not callable using a `const` object +fail_compilation/diag6707.d(13): Consider adding `const` or `inout` here --- */ diff --git a/tests/dmd/fail_compilation/diag8101b.d b/tests/dmd/fail_compilation/diag8101b.d index b1e168df498..a55ef731ad2 100644 --- a/tests/dmd/fail_compilation/diag8101b.d +++ b/tests/dmd/fail_compilation/diag8101b.d @@ -1,17 +1,16 @@ /* TEST_OUTPUT: --- -fail_compilation/diag8101b.d(29): Error: none of the overloads of `foo` are callable using argument types `(double)` -fail_compilation/diag8101b.d(20): Candidates are: `diag8101b.S.foo(int __param_0)` -fail_compilation/diag8101b.d(21): `diag8101b.S.foo(int __param_0, int __param_1)` -fail_compilation/diag8101b.d(31): Error: function `diag8101b.S.bar(int __param_0)` is not callable using argument types `(double)` -fail_compilation/diag8101b.d(31): cannot pass argument `1.0` of type `double` to parameter `int __param_0` -fail_compilation/diag8101b.d(34): Error: none of the overloads of `foo` are callable using a `const` object -fail_compilation/diag8101b.d(20): Candidates are: `diag8101b.S.foo(int __param_0)` -fail_compilation/diag8101b.d(21): `diag8101b.S.foo(int __param_0, int __param_1)` -fail_compilation/diag8101b.d(36): Error: mutable method `bar` is not callable using a `const` object -fail_compilation/diag8101b.d(23): `diag8101b.S.bar(int __param_0)` declared here -fail_compilation/diag8101b.d(23): Consider adding `const` or `inout` +fail_compilation/diag8101b.d(28): Error: none of the overloads of `foo` are callable using argument types `(double)` +fail_compilation/diag8101b.d(19): Candidates are: `diag8101b.S.foo(int __param_0)` +fail_compilation/diag8101b.d(20): `diag8101b.S.foo(int __param_0, int __param_1)` +fail_compilation/diag8101b.d(30): Error: function `diag8101b.S.bar(int __param_0)` is not callable using argument types `(double)` +fail_compilation/diag8101b.d(30): cannot pass argument `1.0` of type `double` to parameter `int __param_0` +fail_compilation/diag8101b.d(33): Error: none of the overloads of `foo` are callable using a `const` object +fail_compilation/diag8101b.d(19): Candidates are: `diag8101b.S.foo(int __param_0)` +fail_compilation/diag8101b.d(20): `diag8101b.S.foo(int __param_0, int __param_1)` +fail_compilation/diag8101b.d(35): Error: mutable method `diag8101b.S.bar` is not callable using a `const` object +fail_compilation/diag8101b.d(22): Consider adding `const` or `inout` here --- */ diff --git a/tests/dmd/fail_compilation/fail217.d b/tests/dmd/fail_compilation/fail217.d index 723e77ccf63..ecae1a38e6d 100644 --- a/tests/dmd/fail_compilation/fail217.d +++ b/tests/dmd/fail_compilation/fail217.d @@ -1,9 +1,8 @@ /* TEST_OUTPUT: --- -fail_compilation/fail217.d(23): Error: mutable constructor `this` cannot construct a `immutable` object -fail_compilation/fail217.d(14): `fail217.Message.this(int notifier_object)` declared here -fail_compilation/fail217.d(14): Consider adding `const` or `inout` +fail_compilation/fail217.d(22): Error: mutable constructor `fail217.Message.this` cannot construct a `immutable` object +fail_compilation/fail217.d(13): Consider adding `const` or `inout` here --- */ diff --git a/tests/dmd/fail_compilation/fail241.d b/tests/dmd/fail_compilation/fail241.d index 0475f240367..babd193033b 100644 --- a/tests/dmd/fail_compilation/fail241.d +++ b/tests/dmd/fail_compilation/fail241.d @@ -1,12 +1,10 @@ /* TEST_OUTPUT: --- -fail_compilation/fail241.d(20): Error: mutable method `f` is not callable using a `const` object -fail_compilation/fail241.d(15): `fail241.Foo.f()` declared here -fail_compilation/fail241.d(15): Consider adding `const` or `inout` -fail_compilation/fail241.d(21): Error: mutable method `g` is not callable using a `const` object -fail_compilation/fail241.d(16): `fail241.Foo.g()` declared here -fail_compilation/fail241.d(16): Consider adding `const` or `inout` +fail_compilation/fail241.d(18): Error: mutable method `fail241.Foo.f` is not callable using a `const` object +fail_compilation/fail241.d(13): Consider adding `const` or `inout` here +fail_compilation/fail241.d(19): Error: mutable method `fail241.Foo.g` is not callable using a `const` object +fail_compilation/fail241.d(14): Consider adding `const` or `inout` here --- */ diff --git a/tests/dmd/fail_compilation/ice9759.d b/tests/dmd/fail_compilation/ice9759.d index 398478fe4d9..6608b58fc0b 100644 --- a/tests/dmd/fail_compilation/ice9759.d +++ b/tests/dmd/fail_compilation/ice9759.d @@ -1,9 +1,8 @@ /* TEST_OUTPUT: --- -fail_compilation/ice9759.d(26): Error: mutable method `opAssign` is not callable using a `const` object -fail_compilation/ice9759.d(18): `ice9759.Json.opAssign(Json v)` declared here -fail_compilation/ice9759.d(18): Consider adding `const` or `inout` +fail_compilation/ice9759.d(25): Error: mutable method `ice9759.Json.opAssign` is not callable using a `const` object +fail_compilation/ice9759.d(17): Consider adding `const` or `inout` here --- */ From 9b83eb475dcd6ea2ab0d74e43c1c8a92acc98e91 Mon Sep 17 00:00:00 2001 From: Nick Treleaven Date: Thu, 16 Nov 2023 16:15:13 +0000 Subject: [PATCH 044/215] Add test Fix Issue 24247 - Improve constructor not callable using $modifier object error --- tests/dmd/fail_compilation/immutable_ctor.d | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 tests/dmd/fail_compilation/immutable_ctor.d diff --git a/tests/dmd/fail_compilation/immutable_ctor.d b/tests/dmd/fail_compilation/immutable_ctor.d new file mode 100644 index 00000000000..408e4027fd6 --- /dev/null +++ b/tests/dmd/fail_compilation/immutable_ctor.d @@ -0,0 +1,19 @@ +/* +TEST_OUTPUT: +--- +fail_compilation/immutable_ctor.d(18): Error: `immutable` copy constructor `immutable_ctor.S1.this` cannot construct a mutable object +--- +*/ + +struct S1 +{ + this(ref const S1 s) immutable { + } + int i; +} + +void main() +{ + const(S1) s1; + S1 ms1 = s1; +} From b59a9cea307a2437b25ba48473e969a017bda9c1 Mon Sep 17 00:00:00 2001 From: RazvanN7 Date: Thu, 16 Nov 2023 16:50:43 +0200 Subject: [PATCH 045/215] Reduce size of dsymbol.ArrayScopeSymbol --- dmd/dsymbol.d | 19 +++++++++---------- dmd/dsymbol.h | 2 -- dmd/frontend.h | 1 - 3 files changed, 9 insertions(+), 13 deletions(-) diff --git a/dmd/dsymbol.d b/dmd/dsymbol.d index a662e5a12a6..1bc7b46f43c 100644 --- a/dmd/dsymbol.d +++ b/dmd/dsymbol.d @@ -1806,25 +1806,24 @@ extern (C++) final class ArrayScopeSymbol : ScopeDsymbol // either a SliceExp, an IndexExp, an ArrayExp, a TypeTuple or a TupleDeclaration. // Discriminated using DYNCAST and, for expressions, also EXP private RootObject arrayContent; - Scope* sc; extern (D) this(Scope* sc, Expression exp) nothrow @safe { super(exp.loc, null); assert(exp.op == EXP.index || exp.op == EXP.slice || exp.op == EXP.array); - this.sc = sc; + this._scope = sc; this.arrayContent = exp; } extern (D) this(Scope* sc, TypeTuple type) nothrow @safe { - this.sc = sc; + this._scope = sc; this.arrayContent = type; } extern (D) this(Scope* sc, TupleDeclaration td) nothrow @safe { - this.sc = sc; + this._scope = sc; this.arrayContent = td; } @@ -1862,10 +1861,10 @@ extern (C++) final class ArrayScopeSymbol : ScopeDsymbol Expression e = new IntegerExp(Loc.initial, td.objects.length, Type.tsize_t); v._init = new ExpInitializer(Loc.initial, e); v.storage_class |= STC.temp | STC.static_ | STC.const_; - v.dsymbolSemantic(sc); + v.dsymbolSemantic(_scope); return v; case type: - return dollarFromTypeTuple(loc, cast(TypeTuple) arrayContent, sc); + return dollarFromTypeTuple(loc, cast(TypeTuple) arrayContent, _scope); default: break; } @@ -1906,7 +1905,7 @@ extern (C++) final class ArrayScopeSymbol : ScopeDsymbol if (auto te = ce.isTypeExp()) { if (auto ttp = te.type.isTypeTuple()) - return dollarFromTypeTuple(loc, ttp, sc); + return dollarFromTypeTuple(loc, ttp, _scope); } /* *pvar is lazily initialized, so if we refer to $ * multiple times, it gets set only once. @@ -1955,7 +1954,7 @@ extern (C++) final class ArrayScopeSymbol : ScopeDsymbol } auto tiargs = new Objects(); Expression edim = new IntegerExp(Loc.initial, dim, Type.tsize_t); - edim = edim.expressionSemantic(sc); + edim = edim.expressionSemantic(_scope); tiargs.push(edim); e = new DotTemplateInstanceExp(loc, ce, td.ident, tiargs); } @@ -1976,7 +1975,7 @@ extern (C++) final class ArrayScopeSymbol : ScopeDsymbol assert(d); e = new DotVarExp(loc, ce, d); } - e = e.expressionSemantic(sc); + e = e.expressionSemantic(_scope); if (!e.type) error(exp.loc, "`%s` has no value", e.toChars()); t = e.type.toBasetype(); @@ -2012,7 +2011,7 @@ extern (C++) final class ArrayScopeSymbol : ScopeDsymbol } *pvar = v; } - (*pvar).dsymbolSemantic(sc); + (*pvar).dsymbolSemantic(_scope); return (*pvar); } diff --git a/dmd/dsymbol.h b/dmd/dsymbol.h index 243b0d78419..eab68aaa137 100644 --- a/dmd/dsymbol.h +++ b/dmd/dsymbol.h @@ -374,8 +374,6 @@ class ArrayScopeSymbol final : public ScopeDsymbol private: RootObject *arrayContent; public: - Scope *sc; - Dsymbol *search(const Loc &loc, Identifier *ident, int flags = IgnoreNone) override; ArrayScopeSymbol *isArrayScopeSymbol() override { return this; } diff --git a/dmd/frontend.h b/dmd/frontend.h index 48e1eef513f..f06e6582354 100644 --- a/dmd/frontend.h +++ b/dmd/frontend.h @@ -6542,7 +6542,6 @@ class ArrayScopeSymbol final : public ScopeDsymbol { RootObject* arrayContent; public: - Scope* sc; Dsymbol* search(const Loc& loc, Identifier* ident, int32_t flags = 0) override; ArrayScopeSymbol* isArrayScopeSymbol() override; void accept(Visitor* v) override; From 90821fd0bcbcb7d2a652aab9d47f26b6502d9f51 Mon Sep 17 00:00:00 2001 From: Yang Yujie Date: Fri, 17 Nov 2023 09:25:47 +0800 Subject: [PATCH 046/215] druntime: adjust LoongArch64 definitions --- runtime/druntime/src/core/stdc/fenv.d | 8 ++-- runtime/druntime/src/core/stdc/stdarg.d | 6 +++ runtime/druntime/src/core/sys/elf/package.d | 2 + .../druntime/src/core/sys/linux/sys/auxv.d | 17 +++++++ .../druntime/src/core/sys/linux/sys/mman.d | 1 + runtime/druntime/src/core/thread/fiber.d | 44 +++++++++++-------- runtime/druntime/src/core/vararg.d | 7 +++ 7 files changed, 63 insertions(+), 22 deletions(-) diff --git a/runtime/druntime/src/core/stdc/fenv.d b/runtime/druntime/src/core/stdc/fenv.d index 288f9c25dc6..0051ecdb7c9 100644 --- a/runtime/druntime/src/core/stdc/fenv.d +++ b/runtime/druntime/src/core/stdc/fenv.d @@ -797,7 +797,7 @@ else } else version (LoongArch64) { - // Define bits representing exceptions in the FPSR status word. + // Define bits representing exceptions in the Flags field in FCSR{0,2}. enum { FE_INEXACT = 0x010000, /// @@ -808,13 +808,13 @@ else FE_ALL_EXCEPT = 0x1f0000, /// } - // Define bits representing rounding modes in the FPCR Rmode field. + // Define bits representing rounding modes in the RM field in FCSR{0,3}. enum { FE_TONEAREST = 0x000, /// FE_TOWARDZERO = 0x100, /// - FE_DOWNWARD = 0x200, /// - FE_UPWARD = 0x300, /// + FE_UPWARD = 0x200, /// + FE_DOWNWARD = 0x300, /// } } else diff --git a/runtime/druntime/src/core/stdc/stdarg.d b/runtime/druntime/src/core/stdc/stdarg.d index 5b79813ae1b..0ba1ebe34e3 100644 --- a/runtime/druntime/src/core/stdc/stdarg.d +++ b/runtime/druntime/src/core/stdc/stdarg.d @@ -257,6 +257,12 @@ T va_arg(T)(ref va_list ap) ap += T.sizeof.alignUp; return *p; } + else version (LoongArch64) + { + auto p = cast(T*) ap; + ap += T.sizeof.alignUp; + return *p; + } else version (MIPS_Any) { auto p = cast(T*) ap; diff --git a/runtime/druntime/src/core/sys/elf/package.d b/runtime/druntime/src/core/sys/elf/package.d index b120ee58f69..60e05d97036 100644 --- a/runtime/druntime/src/core/sys/elf/package.d +++ b/runtime/druntime/src/core/sys/elf/package.d @@ -339,6 +339,8 @@ enum EM_CSKY = 252; enum EM_NUM = 253; +enum EM_LOONGARCH = 258; + enum EM_ALPHA = 0x9026; enum EV_NONE = 0; diff --git a/runtime/druntime/src/core/sys/linux/sys/auxv.d b/runtime/druntime/src/core/sys/linux/sys/auxv.d index 5f098e98e02..1099fae497f 100644 --- a/runtime/druntime/src/core/sys/linux/sys/auxv.d +++ b/runtime/druntime/src/core/sys/linux/sys/auxv.d @@ -13,6 +13,7 @@ extern (C): version (MIPS32) version = MIPS_Any; version (MIPS64) version = MIPS_Any; +version (LoongArch64) version = LoongArch_Any; version (PPC) version = PPC_Any; version (PPC64) version = PPC_Any; version (S390) version = IBMZ_Any; @@ -156,3 +157,19 @@ else version (IBMZ_Any) enum HWCAP_S390_TE = 1024; enum HWCAP_S390_VX = 2048; } +else version (LoongArch_Any) +{ + enum HWCAP_LOONGARCH_CPUCFG = 0x00000001; + enum HWCAP_LOONGARCH_LAM = 0x00000002; + enum HWCAP_LOONGARCH_UAL = 0x00000004; + enum HWCAP_LOONGARCH_FPU = 0x00000008; + enum HWCAP_LOONGARCH_LSX = 0x00000010; + enum HWCAP_LOONGARCH_LASX = 0x00000020; + enum HWCAP_LOONGARCH_CRC32 = 0x00000040; + enum HWCAP_LOONGARCH_COMPLEX = 0x00000080; + enum HWCAP_LOONGARCH_CRYPTO = 0x00000100; + enum HWCAP_LOONGARCH_LVZ = 0x00000200; + enum HWCAP_LOONGARCH_LBT_X86 = 0x00000400; + enum HWCAP_LOONGARCH_LBT_ARM = 0x00000800; + enum HWCAP_LOONGARCH_LBT_MIPS = 0x00001000; +} diff --git a/runtime/druntime/src/core/sys/linux/sys/mman.d b/runtime/druntime/src/core/sys/linux/sys/mman.d index 7ed78ef6436..e4765af1490 100644 --- a/runtime/druntime/src/core/sys/linux/sys/mman.d +++ b/runtime/druntime/src/core/sys/linux/sys/mman.d @@ -432,6 +432,7 @@ else version (MIPS_Any) MAP_HUGETLB = 0x80000, } } +// http://sourceware.org/git/?p=glibc.git;a=blob;f=sysdeps/unix/sysv/linux/bits/mman-map-flags-generic.h else version (LoongArch64) { static if (_DEFAULT_SOURCE) enum diff --git a/runtime/druntime/src/core/thread/fiber.d b/runtime/druntime/src/core/thread/fiber.d index 1bc5ecbd222..5635088a5f7 100644 --- a/runtime/druntime/src/core/thread/fiber.d +++ b/runtime/druntime/src/core/thread/fiber.d @@ -128,8 +128,12 @@ private } else version (LoongArch64) { - version = AsmLoongArch64_Posix; - version = AsmExternal; + version (Posix) + { + version = AsmLoongArch64_Posix; + version = AsmExternal; + version = AlignFiberStackTo16Byte; + } } version (Posix) @@ -1393,24 +1397,28 @@ private: } else version (AsmLoongArch64_Posix) { + // Like others, FP registers and return address ($r1) are kept + // below the saved stack top (tstack) to hide from GC scanning. + // fiber_switchContext expects newp sp to look like this: + // 10: $r21 (reserved) + // 9: $r22 (frame pointer) + // 8: $r23 + // ... + // 0: $r31 <-- newp tstack + // -1: $r1 (return address) [&fiber_entryPoint] + // -2: $f24 + // ... + // -9: $f31 + version (StackGrowsDown) {} - else static assert(0); + else + static assert(false, "Only full descending stacks supported on LoongArch64"); - // Like others, FP registers and return address (ra) are kept - // below the saved stack top (tstack) to hide from GC scanning. - // The newp stack should look like this on LoongArch64: - // 18: fp <- pstack - // ... - // 9: s0 <- newp tstack - // 8: ra [&fiber_entryPoint] - // 7: fs7 - // ... - // 1: fs1 - // 0: fs0 - pstack -= 10 * size_t.sizeof; // skip s0-s8 and fp - // set $ra - push( cast(size_t) &fiber_entryPoint ); - pstack += size_t.sizeof; + // Only need to set return address ($r1). Everything else is fine + // zero initialized. + pstack -= size_t.sizeof * 11; // skip past space reserved for $r21-$r31 + push (cast(size_t) &fiber_entryPoint); + pstack += size_t.sizeof; // adjust sp (newp) above lr } else version (AsmAArch64_Posix) { diff --git a/runtime/druntime/src/core/vararg.d b/runtime/druntime/src/core/vararg.d index 2c3e9659fb6..e6dd47d06d3 100644 --- a/runtime/druntime/src/core/vararg.d +++ b/runtime/druntime/src/core/vararg.d @@ -129,6 +129,13 @@ void va_arg()(ref va_list ap, TypeInfo ti, void* parmn) ap += tsize.alignUp; parmn[0..tsize] = p[0..tsize]; } + else version (LoongArch64) + { + const tsize = ti.tsize; + auto p = cast(void*) ap; + ap += tsize.alignUp; + parmn[0..tsize] = p[0..tsize]; + } else version (MIPS_Any) { const tsize = ti.tsize; From a9af24f59c908205ce5ffb65a1485fce9eb72782 Mon Sep 17 00:00:00 2001 From: Teodor Dutu Date: Fri, 17 Nov 2023 09:57:30 +0200 Subject: [PATCH 047/215] Translate `_d_newarray{mTX, miTX, Op}` to a single template (dlang/dmd!15819) - Move code for `_d_newarraymTX` to `core.internal.array.construction` - Remove `_d_newarraymiTX` and `_d_newarraymOp` - Add unittests for `_d_newarraymTX` - Move lowering to `_d_newarraymTX` to the semantic phase - Inline the lowering when inlining `NewExp`s - Add changelog entry about the new hook Signed-off-by: Teodor Dutu --- dmd/expressionsem.d | 69 ++++++++--- dmd/frontend.h | 2 + dmd/id.d | 2 + dmd/inline.d | 2 +- .../src/core/internal/array/construction.d | 108 ++++++++++++++++++ runtime/druntime/src/object.d | 2 + runtime/druntime/src/rt/lifetime.d | 92 --------------- runtime/druntime/src/rt/tracegc.d | 2 - .../profile/myprofilegc.log.freebsd.32.exp | 6 +- .../profile/myprofilegc.log.freebsd.64.exp | 6 +- .../test/profile/myprofilegc.log.linux.32.exp | 6 +- .../test/profile/myprofilegc.log.linux.64.exp | 6 +- .../test/profile/myprofilegc.log.osx.32.exp | 6 +- .../test/profile/myprofilegc.log.osx.64.exp | 6 +- 14 files changed, 193 insertions(+), 122 deletions(-) diff --git a/dmd/expressionsem.d b/dmd/expressionsem.d index c5a27473c28..09debd0af3f 100644 --- a/dmd/expressionsem.d +++ b/dmd/expressionsem.d @@ -2150,7 +2150,7 @@ private bool checkNogc(FuncDeclaration f, ref Loc loc, Scope* sc) * verified instead. This is to keep errors related to the original code * and not the lowering. */ - if (f.ident == Id._d_newitemT || f.ident == Id._d_newarrayT) + if (f.ident == Id._d_newitemT || f.ident == Id._d_newarrayT || f.ident == Id._d_newarraymTX) return false; if (!f.isNogc()) @@ -5115,23 +5115,23 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor tb = tb.isTypeDArray().next.toBasetype(); } - if (nargs == 1) - { - if (global.params.betterC || !sc.needsCodegen()) + if (global.params.betterC || !sc.needsCodegen()) goto LskipNewArrayLowering; - /* Class types may inherit base classes that have errors. - * This may leak errors from the base class to the derived one - * and then to the hook. Semantic analysis is performed eagerly - * to a void this. - */ - if (auto tc = exp.type.nextOf.isTypeClass()) - { - tc.sym.dsymbolSemantic(sc); - if (tc.sym.errors) - goto LskipNewArrayLowering; - } + /* Class types may inherit base classes that have errors. + * This may leak errors from the base class to the derived one + * and then to the hook. Semantic analysis is performed eagerly + * to a void this. + */ + if (auto tc = exp.type.nextOf.isTypeClass()) + { + tc.sym.dsymbolSemantic(sc); + if (tc.sym.errors) + goto LskipNewArrayLowering; + } + if (nargs == 1) + { auto hook = global.params.tracegc ? Id._d_newarrayTTrace : Id._d_newarrayT; if (!verifyHookExist(exp.loc, *sc, hook, "new array")) goto LskipNewArrayLowering; @@ -5163,6 +5163,45 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor arguments.push((*exp.arguments)[0]); arguments.push(new IntegerExp(exp.loc, isShared, Type.tbool)); + lowering = new CallExp(exp.loc, lowering, arguments); + exp.lowering = lowering.expressionSemantic(sc); + } + else + { + auto hook = global.params.tracegc ? Id._d_newarraymTXTrace : Id._d_newarraymTX; + if (!verifyHookExist(exp.loc, *sc, hook, "new multi-dimensional array")) + goto LskipNewArrayLowering; + + /* Lower the memory allocation and initialization of `new T[][]...[](n1, n2, ...)` + * to `_d_newarraymTX!(T[][]...[], T)([n1, n2, ...])`. + */ + Expression lowering = new IdentifierExp(exp.loc, Id.empty); + lowering = new DotIdExp(exp.loc, lowering, Id.object); + + auto tbn = exp.type.nextOf(); + while (tbn.ty == Tarray) + tbn = tbn.nextOf(); + auto unqualTbn = tbn.unqualify(MODFlags.wild | MODFlags.const_ | + MODFlags.immutable_ | MODFlags.shared_); + + auto tiargs = new Objects(); + tiargs.push(exp.type); + tiargs.push(unqualTbn); + lowering = new DotTemplateInstanceExp(exp.loc, lowering, hook, tiargs); + + auto arguments = new Expressions(); + if (global.params.tracegc) + { + auto funcname = (sc.callsc && sc.callsc.func) ? + sc.callsc.func.toPrettyChars() : sc.func.toPrettyChars(); + arguments.push(new StringExp(exp.loc, exp.loc.filename.toDString())); + arguments.push(new IntegerExp(exp.loc, exp.loc.linnum, Type.tint32)); + arguments.push(new StringExp(exp.loc, funcname.toDString())); + } + + arguments.push(new ArrayLiteralExp(exp.loc, Type.tsize_t.sarrayOf(nargs), exp.arguments)); + arguments.push(new IntegerExp(exp.loc, tbn.isShared(), Type.tbool)); + lowering = new CallExp(exp.loc, lowering, arguments); exp.lowering = lowering.expressionSemantic(sc); } diff --git a/dmd/frontend.h b/dmd/frontend.h index f06e6582354..950aa92bb74 100644 --- a/dmd/frontend.h +++ b/dmd/frontend.h @@ -8654,6 +8654,8 @@ struct Id final static Identifier* _d_newitemTTrace; static Identifier* _d_newarrayT; static Identifier* _d_newarrayTTrace; + static Identifier* _d_newarraymTX; + static Identifier* _d_newarraymTXTrace; static Identifier* _d_assert_fail; static Identifier* dup; static Identifier* _aaApply; diff --git a/dmd/id.d b/dmd/id.d index 5fcda91b435..9887218cfb9 100644 --- a/dmd/id.d +++ b/dmd/id.d @@ -323,6 +323,8 @@ immutable Msgtable[] msgtable = { "_d_newitemTTrace" }, { "_d_newarrayT" }, { "_d_newarrayTTrace" }, + { "_d_newarraymTX" }, + { "_d_newarraymTXTrace" }, { "_d_assert_fail" }, { "dup" }, { "_aaApply" }, diff --git a/dmd/inline.d b/dmd/inline.d index 77093f0faf6..f54188c088c 100644 --- a/dmd/inline.d +++ b/dmd/inline.d @@ -727,7 +727,7 @@ public: auto lowering = ne.lowering; if (lowering) if (auto ce = lowering.isCallExp()) - if (ce.f.ident == Id._d_newarrayT) + if (ce.f.ident == Id._d_newarrayT || ce.f.ident == Id._d_newarraymTX) { ne.lowering = doInlineAs!Expression(lowering, ids); goto LhasLowering; diff --git a/runtime/druntime/src/core/internal/array/construction.d b/runtime/druntime/src/core/internal/array/construction.d index 54f8767139c..655acc8db57 100644 --- a/runtime/druntime/src/core/internal/array/construction.d +++ b/runtime/druntime/src/core/internal/array/construction.d @@ -486,3 +486,111 @@ version (D_ProfileGC) assert(0, "Cannot create new array if compiling without support for runtime type information!"); } } + +/** + * Create a new multi-dimensional array. Also initalize elements if their type has an initializer. + * Otherwise, not zero-initialize the array. + * + * --- + * void main() + * { + * S[][] s = new S[][](2, 3) + * + * // lowering: + * S[] s = _d_newarraymTX!(S[][], S)([2, 3]); + * } + * --- + * + * Params: + * dims = array length values for each dimension + * isShared = whether the array should be shared + * + * Returns: + * newly allocated array + */ +Tarr _d_newarraymTX(Tarr : U[], T, U)(size_t[] dims, bool isShared=false) @trusted +{ + debug(PRINTF) printf("_d_newarraymTX(dims.length = %d)\n", dims.length); + + if (dims.length == 0) + return null; + + alias UnqT = Unqual!(T); + + void[] __allocateInnerArray(size_t[] dims) + { + import core.internal.array.utils : __arrayStart, __setArrayAllocLength, __arrayAlloc; + + auto dim = dims[0]; + + debug(PRINTF) printf("__allocateInnerArray(ti = %p, ti.next = %p, dim = %d, ndims = %d\n", ti, ti.next, dim, dims.length); + if (dims.length == 1) + { + auto r = _d_newarrayT!UnqT(dim, isShared); + return *cast(void[]*)(&r); + } + + auto allocSize = (void[]).sizeof * dim; + auto info = __arrayAlloc!UnqT(allocSize); + __setArrayAllocLength!UnqT(info, allocSize, isShared); + auto p = __arrayStart(info)[0 .. dim]; + + foreach (i; 0..dim) + { + (cast(void[]*)p.ptr)[i] = __allocateInnerArray(dims[1..$]); + } + return p; + } + + auto result = __allocateInnerArray(dims); + debug(PRINTF) printf("result = %llx\n", result.ptr); + + return (cast(U*) result.ptr)[0 .. dims[0]]; +} + +unittest +{ + int[][] a = _d_newarraymTX!(int[][], int)([2, 3]); + + assert(a.length == 2); + for (size_t i = 0; i < a.length; i++) + { + assert(a[i].length == 3); + for (size_t j = 0; j < a[i].length; j++) + assert(a[i][j] == 0); + } +} + +unittest +{ + struct S { int x = 1; } + + S[][] a = _d_newarraymTX!(S[][], S)([2, 3]); + + assert(a.length == 2); + for (size_t i = 0; i < a.length; i++) + { + assert(a[i].length == 3); + for (size_t j = 0; j < a[i].length; j++) + assert(a[i][j].x == 1); + } +} + +version (D_ProfileGC) +{ + /** + * TraceGC wrapper around $(REF _d_newarraymT, core,internal,array,construction). + */ + Tarr _d_newarraymTXTrace(Tarr : U[], T, U)(string file, int line, string funcname, size_t[] dims, bool isShared=false) @trusted + { + version (D_TypeInfo) + { + import core.internal.array.utils : TraceHook, gcStatsPure, accumulatePure; + mixin(TraceHook!(T.stringof, "_d_newarraymTX")); + + return _d_newarraymTX!(Tarr, T)(dims, isShared); + } + else + assert(0, "Cannot create new multi-dimensional array if compiling without support for runtime type information!"); + } +} diff --git a/runtime/druntime/src/object.d b/runtime/druntime/src/object.d index c6e0fc45d63..5c6f8edc1af 100644 --- a/runtime/druntime/src/object.d +++ b/runtime/druntime/src/object.d @@ -4669,6 +4669,7 @@ version (D_ProfileGC) public import core.internal.array.concatenation : _d_arraycatnTXTrace; public import core.lifetime : _d_newitemTTrace; public import core.internal.array.construction : _d_newarrayTTrace; + public import core.internal.array.construction : _d_newarraymTXTrace; } public import core.internal.array.appending : _d_arrayappendcTXImpl; public import core.internal.array.comparison : __cmp; @@ -4678,6 +4679,7 @@ public import core.internal.array.concatenation : _d_arraycatnTX; public import core.internal.array.construction : _d_arrayctor; public import core.internal.array.construction : _d_arraysetctor; public import core.internal.array.construction : _d_newarrayT; +public import core.internal.array.construction : _d_newarraymTX; public import core.internal.array.arrayassign : _d_arrayassign_l; public import core.internal.array.arrayassign : _d_arrayassign_r; public import core.internal.array.arrayassign : _d_arraysetassign; diff --git a/runtime/druntime/src/rt/lifetime.d b/runtime/druntime/src/rt/lifetime.d index af3c6bb1296..8ce2d564bd6 100644 --- a/runtime/druntime/src/rt/lifetime.d +++ b/runtime/druntime/src/rt/lifetime.d @@ -1041,98 +1041,6 @@ extern (C) void[] _d_newarrayiT(const TypeInfo ti, size_t length) pure nothrow @ } } - -/* - * Helper for creating multi-dimensional arrays - */ -private void[] _d_newarrayOpT(alias op)(const TypeInfo ti, size_t[] dims) -{ - debug(PRINTF) printf("_d_newarrayOpT(ndims = %d)\n", dims.length); - if (dims.length == 0) - return null; - - void[] foo(const TypeInfo ti, size_t[] dims) - { - auto tinext = unqualify(ti.next); - auto dim = dims[0]; - - debug(PRINTF) printf("foo(ti = %p, ti.next = %p, dim = %d, ndims = %d\n", ti, ti.next, dim, dims.length); - if (dims.length == 1) - { - auto r = op(ti, dim); - return *cast(void[]*)(&r); - } - - auto allocsize = (void[]).sizeof * dim; - auto info = __arrayAlloc(allocsize, ti, tinext); - auto isshared = typeid(ti) is typeid(TypeInfo_Shared); - __setArrayAllocLength(info, allocsize, isshared, tinext); - auto p = __arrayStart(info)[0 .. dim]; - - foreach (i; 0..dim) - { - (cast(void[]*)p.ptr)[i] = foo(tinext, dims[1..$]); - } - return p; - } - - auto result = foo(ti, dims); - debug(PRINTF) printf("result = %llx\n", result.ptr); - - return result; -} - - -/** -Create a new multi-dimensional array - -Has two variants: -- `_d_newarraymTX` which initializes to 0 -- `_d_newarraymiTX` which initializes elements based on `TypeInfo` - ---- -void main() -{ - new int[][](10, 20); - // _d_newarraymTX(typeid(float), [10, 20]); - - new float[][][](10, 20, 30); - // _d_newarraymiTX(typeid(float), [10, 20, 30]); -} ---- - -Params: - ti = `TypeInfo` of the array type - dims = array length values for each dimension - -Returns: - newly allocated array -*/ -extern (C) void[] _d_newarraymTX(const TypeInfo ti, size_t[] dims) @weak -{ - debug(PRINTF) printf("_d_newarraymT(dims.length = %d)\n", dims.length); - - if (dims.length == 0) - return null; - else - { - return _d_newarrayOpT!(_d_newarrayT)(ti, dims); - } -} - -/// ditto -extern (C) void[] _d_newarraymiTX(const TypeInfo ti, size_t[] dims) @weak -{ - debug(PRINTF) printf("_d_newarraymiT(dims.length = %d)\n", dims.length); - - if (dims.length == 0) - return null; - else - { - return _d_newarrayOpT!(_d_newarrayiT)(ti, dims); - } -} - /** Non-template version of $(REF _d_newitemT, core,lifetime) that does not perform initialization. Needed for $(REF allocEntry, rt,aaA). diff --git a/runtime/druntime/src/rt/tracegc.d b/runtime/druntime/src/rt/tracegc.d index 6ff9c2b433c..24aa19bc6b0 100644 --- a/runtime/druntime/src/rt/tracegc.d +++ b/runtime/druntime/src/rt/tracegc.d @@ -17,8 +17,6 @@ module rt.tracegc; // version = tracegc; -extern (C) void[] _d_newarraymTX(const TypeInfo ti, size_t[] dims); -extern (C) void[] _d_newarraymiTX(const TypeInfo ti, size_t[] dims); extern (C) void _d_callfinalizer(void* p); extern (C) void _d_callinterfacefinalizer(void *p); extern (C) void _d_delclass(Object* p); diff --git a/runtime/druntime/test/profile/myprofilegc.log.freebsd.32.exp b/runtime/druntime/test/profile/myprofilegc.log.freebsd.32.exp index 5a6a451dd62..8a04f4737ac 100644 --- a/runtime/druntime/test/profile/myprofilegc.log.freebsd.32.exp +++ b/runtime/druntime/test/profile/myprofilegc.log.freebsd.32.exp @@ -1,7 +1,7 @@ bytes allocated, allocations, type, function, file:line 256 1 immutable(char)[][int] D main src/profilegc.d:23 - 128 1 float[][] D main src/profilegc.d:18 - 128 1 int[][] D main src/profilegc.d:15 + 128 1 float D main src/profilegc.d:18 + 128 1 int D main src/profilegc.d:15 64 1 double[] profilegc.main src/profilegc.d:56 48 1 float[] D main src/profilegc.d:42 48 1 int[] D main src/profilegc.d:41 @@ -14,6 +14,8 @@ bytes allocated, allocations, type, function, file:line 16 1 float D main src/profilegc.d:17 16 1 int D main src/profilegc.d:13 16 1 int D main src/profilegc.d:14 + 16 1 uint[] D main src/profilegc.d:15 + 16 1 uint[] D main src/profilegc.d:18 16 1 int[] D main src/profilegc.d:22 16 1 int[] D main src/profilegc.d:37 16 1 wchar[] D main src/profilegc.d:35 diff --git a/runtime/druntime/test/profile/myprofilegc.log.freebsd.64.exp b/runtime/druntime/test/profile/myprofilegc.log.freebsd.64.exp index 794f01f62f5..2d0d970a0fc 100644 --- a/runtime/druntime/test/profile/myprofilegc.log.freebsd.64.exp +++ b/runtime/druntime/test/profile/myprofilegc.log.freebsd.64.exp @@ -1,11 +1,13 @@ bytes allocated, allocations, type, function, file:line 464 1 immutable(char)[][int] D main src/profilegc.d:23 - 160 1 float[][] D main src/profilegc.d:18 - 160 1 int[][] D main src/profilegc.d:15 + 160 1 float D main src/profilegc.d:18 + 160 1 int D main src/profilegc.d:15 64 1 double[] profilegc.main src/profilegc.d:56 48 1 float[] D main src/profilegc.d:42 48 1 int[] D main src/profilegc.d:41 32 1 C D main src/profilegc.d:12 + 32 1 ulong[] D main src/profilegc.d:15 + 32 1 ulong[] D main src/profilegc.d:18 32 1 void[] profilegc.main src/profilegc.d:55 16 1 char[] D main src/profilegc.d:34 16 1 char[] D main src/profilegc.d:36 diff --git a/runtime/druntime/test/profile/myprofilegc.log.linux.32.exp b/runtime/druntime/test/profile/myprofilegc.log.linux.32.exp index 5a6a451dd62..9d929c3cca4 100644 --- a/runtime/druntime/test/profile/myprofilegc.log.linux.32.exp +++ b/runtime/druntime/test/profile/myprofilegc.log.linux.32.exp @@ -1,7 +1,7 @@ bytes allocated, allocations, type, function, file:line 256 1 immutable(char)[][int] D main src/profilegc.d:23 - 128 1 float[][] D main src/profilegc.d:18 - 128 1 int[][] D main src/profilegc.d:15 + 128 1 float D main src/profilegc.d:18 + 128 1 int D main src/profilegc.d:15 64 1 double[] profilegc.main src/profilegc.d:56 48 1 float[] D main src/profilegc.d:42 48 1 int[] D main src/profilegc.d:41 @@ -16,4 +16,6 @@ bytes allocated, allocations, type, function, file:line 16 1 int D main src/profilegc.d:14 16 1 int[] D main src/profilegc.d:22 16 1 int[] D main src/profilegc.d:37 + 16 1 uint[] D main src/profilegc.d:15 + 16 1 uint[] D main src/profilegc.d:18 16 1 wchar[] D main src/profilegc.d:35 diff --git a/runtime/druntime/test/profile/myprofilegc.log.linux.64.exp b/runtime/druntime/test/profile/myprofilegc.log.linux.64.exp index 794f01f62f5..2d0d970a0fc 100644 --- a/runtime/druntime/test/profile/myprofilegc.log.linux.64.exp +++ b/runtime/druntime/test/profile/myprofilegc.log.linux.64.exp @@ -1,11 +1,13 @@ bytes allocated, allocations, type, function, file:line 464 1 immutable(char)[][int] D main src/profilegc.d:23 - 160 1 float[][] D main src/profilegc.d:18 - 160 1 int[][] D main src/profilegc.d:15 + 160 1 float D main src/profilegc.d:18 + 160 1 int D main src/profilegc.d:15 64 1 double[] profilegc.main src/profilegc.d:56 48 1 float[] D main src/profilegc.d:42 48 1 int[] D main src/profilegc.d:41 32 1 C D main src/profilegc.d:12 + 32 1 ulong[] D main src/profilegc.d:15 + 32 1 ulong[] D main src/profilegc.d:18 32 1 void[] profilegc.main src/profilegc.d:55 16 1 char[] D main src/profilegc.d:34 16 1 char[] D main src/profilegc.d:36 diff --git a/runtime/druntime/test/profile/myprofilegc.log.osx.32.exp b/runtime/druntime/test/profile/myprofilegc.log.osx.32.exp index 87edaf1d909..e5afe3345e0 100644 --- a/runtime/druntime/test/profile/myprofilegc.log.osx.32.exp +++ b/runtime/druntime/test/profile/myprofilegc.log.osx.32.exp @@ -1,7 +1,7 @@ bytes allocated, allocations, type, function, file:line 176 1 immutable(char)[][int] D main src/profilegc.d:23 - 128 1 float[][] D main src/profilegc.d:18 - 128 1 int[][] D main src/profilegc.d:15 + 128 1 float D main src/profilegc.d:18 + 128 1 int D main src/profilegc.d:15 64 1 float[] D main src/profilegc.d:42 64 1 int[] D main src/profilegc.d:41 64 1 double[] profilegc.main src/profilegc.d:56 @@ -14,6 +14,8 @@ bytes allocated, allocations, type, function, file:line 16 1 float D main src/profilegc.d:17 16 1 int D main src/profilegc.d:13 16 1 int D main src/profilegc.d:14 + 16 1 uint[] D main src/profilegc.d:15 + 16 1 uint[] D main src/profilegc.d:18 16 1 int[] D main src/profilegc.d:22 16 1 int[] D main src/profilegc.d:37 16 1 wchar[] D main src/profilegc.d:35 diff --git a/runtime/druntime/test/profile/myprofilegc.log.osx.64.exp b/runtime/druntime/test/profile/myprofilegc.log.osx.64.exp index 794f01f62f5..2d0d970a0fc 100644 --- a/runtime/druntime/test/profile/myprofilegc.log.osx.64.exp +++ b/runtime/druntime/test/profile/myprofilegc.log.osx.64.exp @@ -1,11 +1,13 @@ bytes allocated, allocations, type, function, file:line 464 1 immutable(char)[][int] D main src/profilegc.d:23 - 160 1 float[][] D main src/profilegc.d:18 - 160 1 int[][] D main src/profilegc.d:15 + 160 1 float D main src/profilegc.d:18 + 160 1 int D main src/profilegc.d:15 64 1 double[] profilegc.main src/profilegc.d:56 48 1 float[] D main src/profilegc.d:42 48 1 int[] D main src/profilegc.d:41 32 1 C D main src/profilegc.d:12 + 32 1 ulong[] D main src/profilegc.d:15 + 32 1 ulong[] D main src/profilegc.d:18 32 1 void[] profilegc.main src/profilegc.d:55 16 1 char[] D main src/profilegc.d:34 16 1 char[] D main src/profilegc.d:36 From 036a1655f18b0dd0956fa27344959d66b5cbe994 Mon Sep 17 00:00:00 2001 From: Walter Bright Date: Fri, 17 Nov 2023 00:19:58 -0800 Subject: [PATCH 048/215] traits.d: remove some casts --- dmd/traits.d | 33 ++++++++++++++++++--------------- 1 file changed, 18 insertions(+), 15 deletions(-) diff --git a/dmd/traits.d b/dmd/traits.d index 79df7fde02b..050d6500094 100644 --- a/dmd/traits.d +++ b/dmd/traits.d @@ -99,8 +99,9 @@ private Dsymbol getDsymbolWithoutExpCtx(RootObject oarg) ulong getTypePointerBitmap(Loc loc, Type t, Array!(ulong)* data) { ulong sz; - if (t.ty == Tclass && !(cast(TypeClass)t).sym.isInterfaceDeclaration()) - sz = (cast(TypeClass)t).sym.AggregateDeclaration.size(loc); + auto tc = t.isTypeClass(); + if (tc && !tc.sym.isInterfaceDeclaration()) + sz = tc.sym.AggregateDeclaration.size(loc); else sz = t.size(loc); if (sz == SIZE_INVALID) @@ -247,7 +248,7 @@ ulong getTypePointerBitmap(Loc loc, Type t, Array!(ulong)* data) visit.VisitType(t); } - if (auto tc = t.isTypeClass()) + if (auto tcx = t.isTypeClass()) { // a "toplevel" class is treated as an instance, while TypeClass fields are treated as references void visitTopLevelClass(TypeClass t) @@ -264,7 +265,7 @@ ulong getTypePointerBitmap(Loc loc, Type t, Array!(ulong)* data) offset = classoff; } - visitTopLevelClass(tc); + visitTopLevelClass(tcx); } else visit(t); @@ -472,13 +473,13 @@ Expression semanticTraits(TraitsExp e, Scope* sc) } if (e.ident == Id.isAbstractClass) { - return isTypeX(t => t.toBasetype().ty == Tclass && - (cast(TypeClass)t.toBasetype()).sym.isAbstract()); + return isTypeX(t => t.toBasetype().isTypeClass() && + t.toBasetype().isTypeClass().sym.isAbstract()); } if (e.ident == Id.isFinalClass) { - return isTypeX(t => t.toBasetype().ty == Tclass && - ((cast(TypeClass)t.toBasetype()).sym.storage_class & STC.final_) != 0); + return isTypeX(t => t.toBasetype().isTypeClass() && + (t.toBasetype().isTypeClass().sym.storage_class & STC.final_) != 0); } if (e.ident == Id.isTemplate) { @@ -508,7 +509,8 @@ Expression semanticTraits(TraitsExp e, Scope* sc) } Type tb = t.baseElemOf(); - if (auto sd = tb.ty == Tstruct ? (cast(TypeStruct)tb).sym : null) + auto ts = tb.isTypeStruct(); + if (auto sd = ts ? ts.sym : null) { return sd.isPOD() ? True() : False(); } @@ -529,7 +531,8 @@ Expression semanticTraits(TraitsExp e, Scope* sc) } Type tb = t.baseElemOf(); - if (auto sd = tb.ty == Tstruct ? (cast(TypeStruct)tb).sym : null) + auto ts = tb.isTypeStruct(); + if (auto sd = ts ? ts.sym : null) { return (e.ident == Id.hasPostblit) ? (sd.postblit ? True() : False()) : (sd.hasCopyCtor ? True() : False()); @@ -793,10 +796,10 @@ Expression semanticTraits(TraitsExp e, Scope* sc) { if (auto p = s.toParent()) // `C`'s parent is `C!2`, believe it or not { - if (p.isTemplateInstance()) // `C!2` is a template instance + if (auto ti = p.isTemplateInstance()) // `C!2` is a template instance { s = p; // `C!2`'s parent is `T1` - auto td = (cast(TemplateInstance)p).tempdecl; + auto td = ti.tempdecl; if (td) s = td; // get the declaration context just in case there's two contexts } @@ -1297,7 +1300,7 @@ Expression semanticTraits(TraitsExp e, Scope* sc) if (fd && fd.parent && fd.parent.isTemplateInstance) { fd.functionSemantic3(); - tf = cast(TypeFunction)fd.type; + tf = fd.type.isTypeFunction(); } auto mods = new Expressions(); @@ -1738,9 +1741,9 @@ Expression semanticTraits(TraitsExp e, Scope* sc) ex = ex.expressionSemantic(sc2); ex = resolvePropertiesOnly(sc2, ex); ex = ex.optimize(WANTvalue); - if (sc2.func && sc2.func.type.ty == Tfunction) + if (sc2.func && sc2.func.type.isTypeFunction()) { - const tf = cast(TypeFunction)sc2.func.type; + const tf = sc2.func.type.isTypeFunction(); err |= tf.isnothrow && canThrow(ex, sc2.func, null); } ex = checkGC(sc2, ex); From c1623283d496e65b7d95b50c4368e7566e7758a5 Mon Sep 17 00:00:00 2001 From: Nick Treleaven Date: Thu, 16 Nov 2023 18:49:17 +0000 Subject: [PATCH 049/215] Fix Issue 24248 - const constructor call with mutable target gives wrong error message --- dmd/func.d | 5 ++++- tests/dmd/fail_compilation/const_ctor.d | 26 +++++++++++++++++++++++++ 2 files changed, 30 insertions(+), 1 deletion(-) create mode 100644 tests/dmd/fail_compilation/const_ctor.d diff --git a/dmd/func.d b/dmd/func.d index eb400d11175..353713d4d0d 100644 --- a/dmd/func.d +++ b/dmd/func.d @@ -3412,7 +3412,10 @@ FuncDeclaration resolveFuncCall(const ref Loc loc, Scope* sc, Dsymbol s, if (!tf) tf = fd.originalType.toTypeFunction(); - if (tthis && !MODimplicitConv(tthis.mod, tf.mod)) // modifier mismatch + // modifier mismatch + if (tthis && (fd.isCtorDeclaration() ? + !MODimplicitConv(tf.mod, tthis.mod) : + !MODimplicitConv(tthis.mod, tf.mod))) { OutBuffer thisBuf, funcBuf; MODMatchToBuffer(&thisBuf, tthis.mod, tf.mod); diff --git a/tests/dmd/fail_compilation/const_ctor.d b/tests/dmd/fail_compilation/const_ctor.d new file mode 100644 index 00000000000..ae37023f0a1 --- /dev/null +++ b/tests/dmd/fail_compilation/const_ctor.d @@ -0,0 +1,26 @@ +/* +TEST_OUTPUT: +--- +fail_compilation/const_ctor.d(23): Error: `const` copy constructor `const_ctor.S1.this` cannot construct a mutable object +fail_compilation/const_ctor.d(25): Error: `const` constructor `const_ctor.S2.this` cannot construct a mutable object +--- +*/ + +struct S1 +{ + this(ref const S1 s) const {} + int* i; +} +struct S2 +{ + this(int) const {} + int* i; +} + +void main() +{ + const(S1) s1; + S1 m1 = s1; + + S2 s2 = S2(5); +} From a77554fb71fafad6939f3774847226106ae2d169 Mon Sep 17 00:00:00 2001 From: Nick Treleaven Date: Thu, 16 Nov 2023 19:57:25 +0000 Subject: [PATCH 050/215] Rebase & fix new test --- dmd/func.d | 2 +- tests/dmd/fail_compilation/ctor_attr.d | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/dmd/func.d b/dmd/func.d index 353713d4d0d..05e4f56c9e7 100644 --- a/dmd/func.d +++ b/dmd/func.d @@ -3423,7 +3423,7 @@ FuncDeclaration resolveFuncCall(const ref Loc loc, Scope* sc, Dsymbol s, if (hasOverloads) { .error(loc, "none of the overloads of `%s` are callable using a %sobject", - fd.ident.toChars(), thisBuf.peekChars()); + fd.toChars(), thisBuf.peekChars()); if (!global.gag || global.params.v.showGaggedErrors) printCandidates(loc, fd, sc.isDeprecated()); return null; diff --git a/tests/dmd/fail_compilation/ctor_attr.d b/tests/dmd/fail_compilation/ctor_attr.d index 2138af64bb5..bdaf4e686d6 100644 --- a/tests/dmd/fail_compilation/ctor_attr.d +++ b/tests/dmd/fail_compilation/ctor_attr.d @@ -1,7 +1,7 @@ /* TEST_OUTPUT: --- -fail_compilation/ctor_attr.d(26): Error: none of the overloads of `this` are callable using argument types `(int)` +fail_compilation/ctor_attr.d(26): Error: none of the overloads of `this` are callable using a mutable object fail_compilation/ctor_attr.d(16): Candidates are: `ctor_attr.S.this(int x) const` fail_compilation/ctor_attr.d(18): `ctor_attr.S.this(string x)` fail_compilation/ctor_attr.d(17): `this()(int x) shared` From 14bb70f72677faedaf5d180689e83c82936efd60 Mon Sep 17 00:00:00 2001 From: Nick Treleaven Date: Thu, 16 Nov 2023 20:09:47 +0000 Subject: [PATCH 051/215] Update a test with __ctor --- tests/dmd/fail_compilation/testrvaluecpctor.d | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/dmd/fail_compilation/testrvaluecpctor.d b/tests/dmd/fail_compilation/testrvaluecpctor.d index 871159afa0c..93cf52aabc4 100644 --- a/tests/dmd/fail_compilation/testrvaluecpctor.d +++ b/tests/dmd/fail_compilation/testrvaluecpctor.d @@ -5,7 +5,7 @@ TEST_OUTPUT: --- fail_compilation/testrvaluecpctor.d(16): Error: cannot define both an rvalue constructor and a copy constructor for `struct Foo` fail_compilation/testrvaluecpctor.d(24): Template instance `testrvaluecpctor.Foo!int.Foo.__ctor!(immutable(Foo!int), immutable(Foo!int))` creates an rvalue constructor for `struct Foo` -fail_compilation/testrvaluecpctor.d(24): Error: none of the overloads of `__ctor` are callable using a `immutable` object +fail_compilation/testrvaluecpctor.d(24): Error: none of the overloads of `this` are callable using a `immutable` object fail_compilation/testrvaluecpctor.d(18): Candidates are: `testrvaluecpctor.Foo!int.Foo.this(ref scope Foo!int rhs)` fail_compilation/testrvaluecpctor.d(16): `this(Rhs, this This)(scope Rhs rhs)` --- From 10a9db069659f3ca144ee8945487c6ad9ee5afd8 Mon Sep 17 00:00:00 2001 From: RazvanN7 Date: Thu, 16 Nov 2023 16:31:26 +0200 Subject: [PATCH 052/215] Move dsymbol.addMember to dsymbolsem and transform it into a visitor --- dmd/attrib.d | 111 +------------- dmd/attrib.h | 7 - dmd/denum.d | 19 --- dmd/dimport.d | 27 ---- dmd/dsymbol.d | 61 -------- dmd/dsymbol.h | 3 +- dmd/dsymbolsem.d | 362 ++++++++++++++++++++++++++++++++++++++++++++- dmd/dversion.d | 75 ---------- dmd/enum.h | 1 - dmd/frontend.h | 18 +-- dmd/import.h | 1 - dmd/nspace.d | 27 ---- dmd/nspace.h | 1 - dmd/staticassert.d | 5 - dmd/staticassert.h | 1 - dmd/version.h | 2 - 16 files changed, 367 insertions(+), 354 deletions(-) diff --git a/dmd/attrib.d b/dmd/attrib.d index 49fc3082ba8..251e2e88ca5 100644 --- a/dmd/attrib.d +++ b/dmd/attrib.d @@ -32,7 +32,7 @@ import dmd.declaration; import dmd.dmodule; import dmd.dscope; import dmd.dsymbol; -import dmd.dsymbolsem : dsymbolSemantic; +import dmd.dsymbolsem; import dmd.errors; import dmd.expression; import dmd.expressionsem; @@ -123,18 +123,6 @@ extern (C++) abstract class AttribDeclaration : Dsymbol return sc; } - override void addMember(Scope* sc, ScopeDsymbol sds) - { - Dsymbols* d = include(sc); - if (d) - { - Scope* sc2 = newScope(sc); - d.foreachDsymbol( s => s.addMember(sc2, sds) ); - if (sc2 != sc) - sc2.pop(); - } - } - override void setScope(Scope* sc) { Dsymbols* d = include(sc); @@ -295,34 +283,6 @@ extern (C++) class StorageClassDeclaration : AttribDeclaration return t; } - override void addMember(Scope* sc, ScopeDsymbol sds) - { - Dsymbols* d = include(sc); - if (d) - { - Scope* sc2 = newScope(sc); - - d.foreachDsymbol( (s) - { - //printf("\taddMember %s to %s\n", s.toChars(), sds.toChars()); - // STC.local needs to be attached before the member is added to the scope (because it influences the parent symbol) - if (auto decl = s.isDeclaration()) - { - decl.storage_class |= stc & STC.local; - if (auto sdecl = s.isStorageClassDeclaration()) // TODO: why is this not enough to deal with the nested case? - { - sdecl.stc |= stc & STC.local; - } - } - s.addMember(sc2, sds); - }); - - if (sc2 != sc) - sc2.pop(); - } - - } - override inout(StorageClassDeclaration) isStorageClassDeclaration() inout { return this; @@ -640,37 +600,6 @@ extern (C++) final class VisibilityDeclaration : AttribDeclaration return createNewScope(sc, sc.stc, sc.linkage, sc.cppmangle, this.visibility, 1, sc.aligndecl, sc.inlining); } - override void addMember(Scope* sc, ScopeDsymbol sds) - { - if (pkg_identifiers) - { - Dsymbol tmp; - Package.resolve(pkg_identifiers, &tmp, null); - visibility.pkg = tmp ? tmp.isPackage() : null; - pkg_identifiers = null; - } - if (visibility.kind == Visibility.Kind.package_ && visibility.pkg && sc._module) - { - Module m = sc._module; - - // https://issues.dlang.org/show_bug.cgi?id=17441 - // While isAncestorPackageOf does an equality check, the fix for the issue adds a check to see if - // each package's .isModule() properites are equal. - // - // Properties generated from `package(foo)` i.e. visibility.pkg have .isModule() == null. - // This breaks package declarations of the package in question if they are declared in - // the same package.d file, which _do_ have a module associated with them, and hence a non-null - // isModule() - if (!m.isPackage() || !visibility.pkg.ident.equals(m.isPackage().ident)) - { - Package pkg = m.parent ? m.parent.isPackage() : null; - if (!pkg || !visibility.pkg.isAncestorPackageOf(pkg)) - .error(loc, "%s `%s` does not bind to one of ancestor packages of module `%s`", kind(), toPrettyChars(false), m.toPrettyChars(true)); - } - } - return AttribDeclaration.addMember(sc, sds); - } - override const(char)* kind() const { return "visibility attribute"; @@ -1054,23 +983,6 @@ extern (C++) final class StaticIfDeclaration : ConditionalDeclaration } } - override void addMember(Scope* sc, ScopeDsymbol sds) - { - //printf("StaticIfDeclaration::addMember() '%s'\n", toChars()); - /* This is deferred until the condition evaluated later (by the include() call), - * so that expressions in the condition can refer to declarations - * in the same scope, such as: - * - * template Foo(int i) - * { - * const int j = i + 1; - * static if (j == 3) - * const int k; - * } - */ - this.scopesym = sds; - } - override void setScope(Scope* sc) { // do not evaluate condition before semantic pass @@ -1186,12 +1098,6 @@ extern (C++) final class StaticForeachDeclaration : AttribDeclaration return d; } - override void addMember(Scope* sc, ScopeDsymbol sds) - { - // used only for caching the enclosing symbol - this.scopesym = sds; - } - override void addComment(const(char)* comment) { // do nothing @@ -1266,15 +1172,6 @@ extern(C++) final class ForwardingAttribDeclaration : AttribDeclaration return sc.push(sym); } - /*************************************** - * Lazily initializes the scope to forward to. - */ - override void addMember(Scope* sc, ScopeDsymbol sds) - { - sym.parent = sds; - return super.addMember(sc, sym); - } - override inout(ForwardingAttribDeclaration) isForwardingAttribDeclaration() inout { return this; @@ -1312,12 +1209,6 @@ extern (C++) final class MixinDeclaration : AttribDeclaration return new MixinDeclaration(loc, Expression.arraySyntaxCopy(exps)); } - override void addMember(Scope* sc, ScopeDsymbol sds) - { - //printf("MixinDeclaration::addMember(sc = %p, sds = %p, memnum = %d)\n", sc, sds, memnum); - this.scopesym = sds; - } - override void setScope(Scope* sc) { Dsymbol.setScope(sc); diff --git a/dmd/attrib.h b/dmd/attrib.h index f47a1f6f836..efea9af950c 100644 --- a/dmd/attrib.h +++ b/dmd/attrib.h @@ -26,7 +26,6 @@ class AttribDeclaration : public Dsymbol virtual Dsymbols *include(Scope *sc); virtual Scope *newScope(Scope *sc); - void addMember(Scope *sc, ScopeDsymbol *sds) override; void setScope(Scope *sc) override; void importAll(Scope *sc) override; void addComment(const utf8_t *comment) override; @@ -49,7 +48,6 @@ class StorageClassDeclaration : public AttribDeclaration StorageClassDeclaration *syntaxCopy(Dsymbol *s) override; Scope *newScope(Scope *sc) override; bool oneMember(Dsymbol **ps, Identifier *ident) override final; - void addMember(Scope *sc, ScopeDsymbol *sds) override; StorageClassDeclaration *isStorageClassDeclaration() override { return this; } void accept(Visitor *v) override { v->visit(this); } @@ -110,7 +108,6 @@ class VisibilityDeclaration final : public AttribDeclaration VisibilityDeclaration *syntaxCopy(Dsymbol *s) override; Scope *newScope(Scope *sc) override; - void addMember(Scope *sc, ScopeDsymbol *sds) override; const char *kind() const override; const char *toPrettyChars(bool unused) override; VisibilityDeclaration *isVisibilityDeclaration() override { return this; } @@ -179,7 +176,6 @@ class StaticIfDeclaration final : public ConditionalDeclaration StaticIfDeclaration *syntaxCopy(Dsymbol *s) override; Dsymbols *include(Scope *sc) override; - void addMember(Scope *sc, ScopeDsymbol *sds) override; void setScope(Scope *sc) override; void importAll(Scope *sc) override; StaticIfDeclaration *isStaticIfDeclaration() override { return this; } @@ -199,7 +195,6 @@ class StaticForeachDeclaration final : public AttribDeclaration StaticForeachDeclaration *syntaxCopy(Dsymbol *s) override; bool oneMember(Dsymbol **ps, Identifier *ident) override; Dsymbols *include(Scope *sc) override; - void addMember(Scope *sc, ScopeDsymbol *sds) override; void addComment(const utf8_t *comment) override; void setScope(Scope *sc) override; void importAll(Scope *sc) override; @@ -213,7 +208,6 @@ class ForwardingAttribDeclaration final : public AttribDeclaration ForwardingScopeDsymbol *sym; Scope *newScope(Scope *sc) override; - void addMember(Scope *sc, ScopeDsymbol *sds) override; ForwardingAttribDeclaration *isForwardingAttribDeclaration() override { return this; } void accept(Visitor *v) override { v->visit(this); } }; @@ -229,7 +223,6 @@ class MixinDeclaration final : public AttribDeclaration d_bool compiled; MixinDeclaration *syntaxCopy(Dsymbol *s) override; - void addMember(Scope *sc, ScopeDsymbol *sds) override; void setScope(Scope *sc) override; const char *kind() const override; void accept(Visitor *v) override { v->visit(this); } diff --git a/dmd/denum.d b/dmd/denum.d index f33b5fd543e..17ec7fb194b 100644 --- a/dmd/denum.d +++ b/dmd/denum.d @@ -83,25 +83,6 @@ extern (C++) final class EnumDeclaration : ScopeDsymbol return ed; } - override void addMember(Scope* sc, ScopeDsymbol sds) - { - version (none) - { - printf("EnumDeclaration::addMember() %s\n", toChars()); - for (size_t i = 0; i < members.length; i++) - { - EnumMember em = (*members)[i].isEnumMember(); - printf(" member %s\n", em.toChars()); - } - } - if (!isAnonymous()) - { - ScopeDsymbol.addMember(sc, sds); - } - - addEnumMembersToSymtab(this, sc, sds); - } - override void setScope(Scope* sc) { if (semanticRun > PASS.initial) diff --git a/dmd/dimport.d b/dmd/dimport.d index d74c8603420..7c1c9319de5 100644 --- a/dmd/dimport.d +++ b/dmd/dimport.d @@ -305,33 +305,6 @@ extern (C++) final class Import : Dsymbol return this; } - /***************************** - * Add import to sd's symbol table. - */ - override void addMember(Scope* sc, ScopeDsymbol sd) - { - //printf("Import.addMember(this=%s, sd=%s, sc=%p)\n", toChars(), sd.toChars(), sc); - if (names.length == 0) - return Dsymbol.addMember(sc, sd); - if (aliasId) - Dsymbol.addMember(sc, sd); - /* Instead of adding the import to sd's symbol table, - * add each of the alias=name pairs - */ - for (size_t i = 0; i < names.length; i++) - { - Identifier name = names[i]; - Identifier _alias = aliases[i]; - if (!_alias) - _alias = name; - auto tname = new TypeIdentifier(loc, name); - auto ad = new AliasDeclaration(loc, _alias, tname); - ad._import = this; - ad.addMember(sc, sd); - aliasdecls.push(ad); - } - } - override void setScope(Scope* sc) { Dsymbol.setScope(sc); diff --git a/dmd/dsymbol.d b/dmd/dsymbol.d index 1bc7b46f43c..1f3801cd094 100644 --- a/dmd/dsymbol.d +++ b/dmd/dsymbol.d @@ -749,67 +749,6 @@ extern (C++) class Dsymbol : ASTNode return toAlias(); } - void addMember(Scope* sc, ScopeDsymbol sds) - { - //printf("Dsymbol::addMember('%s')\n", toChars()); - //printf("Dsymbol::addMember(this = %p, '%s' scopesym = '%s')\n", this, toChars(), sds.toChars()); - //printf("Dsymbol::addMember(this = %p, '%s' sds = %p, sds.symtab = %p)\n", this, toChars(), sds, sds.symtab); - parent = sds; - if (isAnonymous()) // no name, so can't add it to symbol table - return; - - if (!sds.symtabInsert(this)) // if name is already defined - { - if (isAliasDeclaration() && !_scope) - setScope(sc); - Dsymbol s2 = sds.symtabLookup(this,ident); - /* https://issues.dlang.org/show_bug.cgi?id=17434 - * - * If we are trying to add an import to the symbol table - * that has already been introduced, then keep the one with - * larger visibility. This is fine for imports because if - * we have multiple imports of the same file, if a single one - * is public then the symbol is reachable. - */ - if (auto i1 = isImport()) - { - if (auto i2 = s2.isImport()) - { - if (sc.explicitVisibility && sc.visibility > i2.visibility) - sds.symtab.update(this); - } - } - - // If using C tag/prototype/forward declaration rules - if (sc.flags & SCOPE.Cfile && !this.isImport()) - { - if (handleTagSymbols(*sc, this, s2, sds)) - return; - if (handleSymbolRedeclarations(*sc, this, s2, sds)) - return; - - sds.multiplyDefined(Loc.initial, this, s2); // ImportC doesn't allow overloading - errors = true; - return; - } - - if (!s2.overloadInsert(this)) - { - sds.multiplyDefined(Loc.initial, this, s2); - errors = true; - } - } - if (sds.isAggregateDeclaration() || sds.isEnumDeclaration()) - { - if (ident == Id.__sizeof || - !(sc && sc.flags & SCOPE.Cfile) && (ident == Id.__xalignof || ident == Id._mangleof)) - { - .error(loc, "%s `%s` `.%s` property cannot be redefined", kind, toPrettyChars, ident.toChars()); - errors = true; - } - } - } - /************************************* * Set scope for future semantic analysis so we can * deal better with forward references. diff --git a/dmd/dsymbol.h b/dmd/dsymbol.h index eab68aaa137..60155761245 100644 --- a/dmd/dsymbol.h +++ b/dmd/dsymbol.h @@ -228,7 +228,6 @@ class Dsymbol : public ASTNode virtual const char *kind() const; virtual Dsymbol *toAlias(); // resolve real symbol virtual Dsymbol *toAlias2(); - virtual void addMember(Scope *sc, ScopeDsymbol *sds); virtual void setScope(Scope *sc); virtual void importAll(Scope *sc); virtual Dsymbol *search(const Loc &loc, Identifier *ident, int flags = IgnoreNone); @@ -434,3 +433,5 @@ class DsymbolTable final : public RootObject // Number of symbols in symbol table size_t length() const; }; + +void addMember(Dsymbol *dsym, Scope *sc, ScopeDsymbol *sds); diff --git a/dmd/dsymbolsem.d b/dmd/dsymbolsem.d index e5bf021d654..5441e254a2f 100644 --- a/dmd/dsymbolsem.d +++ b/dmd/dsymbolsem.d @@ -23,6 +23,7 @@ import dmd.astenums; import dmd.attrib; import dmd.blockexit; import dmd.clone; +import dmd.cond; import dmd.compiler; import dmd.dcast; import dmd.dclass; @@ -1979,7 +1980,7 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor if (!cd.compiled) { cd.decl = compileIt(cd); - cd.AttribDeclaration.addMember(sc, cd.scopesym); + attribAddMember(cd, sc, cd.scopesym); cd.compiled = true; if (cd._scope && cd.decl) @@ -5831,6 +5832,365 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor } } +/* +Adds dsym as a member of scope sds. + +Params: + dsym = dsymbol to inserted + sc = scope where the dsymbol is declared + sds = ScopeDsymbol where dsym is inserted +*/ +extern(C++) void addMember(Dsymbol dsym, Scope* sc, ScopeDsymbol sds) +{ + auto addMemberVisitor = new AddMemberVisitor(sc, sds); + dsym.accept(addMemberVisitor); +} + +private void attribAddMember(AttribDeclaration atb, Scope* sc, ScopeDsymbol sds) +{ + Dsymbols* d = atb.include(sc); + if (d) + { + Scope* sc2 = atb.newScope(sc); + d.foreachDsymbol( s => s.addMember(sc2, sds) ); + if (sc2 != sc) + sc2.pop(); + } +} + +private extern(C++) class AddMemberVisitor : Visitor +{ + alias visit = Visitor.visit; + + Scope* sc; + ScopeDsymbol sds; + + this(Scope* sc, ScopeDsymbol sds) + { + this.sc = sc; + this.sds = sds; + } + + override void visit(Dsymbol dsym) + { + //printf("Dsymbol::addMember('%s')\n", toChars()); + //printf("Dsymbol::addMember(this = %p, '%s' scopesym = '%s')\n", this, toChars(), sds.toChars()); + //printf("Dsymbol::addMember(this = %p, '%s' sds = %p, sds.symtab = %p)\n", this, toChars(), sds, sds.symtab); + dsym.parent = sds; + if (dsym.isAnonymous()) // no name, so can't add it to symbol table + return; + + if (!sds.symtabInsert(dsym)) // if name is already defined + { + if (dsym.isAliasDeclaration() && !dsym._scope) + dsym.setScope(sc); + Dsymbol s2 = sds.symtabLookup(dsym, dsym.ident); + /* https://issues.dlang.org/show_bug.cgi?id=17434 + * + * If we are trying to add an import to the symbol table + * that has already been introduced, then keep the one with + * larger visibility. This is fine for imports because if + * we have multiple imports of the same file, if a single one + * is public then the symbol is reachable. + */ + if (auto i1 = dsym.isImport()) + { + if (auto i2 = s2.isImport()) + { + if (sc.explicitVisibility && sc.visibility > i2.visibility) + sds.symtab.update(dsym); + } + } + + // If using C tag/prototype/forward declaration rules + if (sc.flags & SCOPE.Cfile && !dsym.isImport()) + { + if (handleTagSymbols(*sc, dsym, s2, sds)) + return; + if (handleSymbolRedeclarations(*sc, dsym, s2, sds)) + return; + + sds.multiplyDefined(Loc.initial, dsym, s2); // ImportC doesn't allow overloading + dsym.errors = true; + return; + } + + if (!s2.overloadInsert(dsym)) + { + sds.multiplyDefined(Loc.initial, dsym, s2); + dsym.errors = true; + } + } + if (sds.isAggregateDeclaration() || sds.isEnumDeclaration()) + { + if (dsym.ident == Id.__sizeof || + !(sc && sc.flags & SCOPE.Cfile) && (dsym.ident == Id.__xalignof || dsym.ident == Id._mangleof)) + { + .error(dsym.loc, "%s `%s` `.%s` property cannot be redefined", dsym.kind, dsym.toPrettyChars, dsym.ident.toChars()); + dsym.errors = true; + } + } + } + + + override void visit(StaticAssert _) + { + // we didn't add anything + } + + /***************************** + * Add import to sd's symbol table. + */ + override void visit(Import imp) + { + //printf("Import.addMember(this=%s, sds=%s, sc=%p)\n", imp.toChars(), sds.toChars(), sc); + if (imp.names.length == 0) + return visit(cast(Dsymbol)imp); + if (imp.aliasId) + visit(cast(Dsymbol)imp); + + /* Instead of adding the import to sds's symbol table, + * add each of the alias=name pairs + */ + for (size_t i = 0; i < imp.names.length; i++) + { + Identifier name = imp.names[i]; + Identifier _alias = imp.aliases[i]; + if (!_alias) + _alias = name; + auto tname = new TypeIdentifier(imp.loc, name); + auto ad = new AliasDeclaration(imp.loc, _alias, tname); + ad._import = imp; + addMember(ad, sc, sds); + imp.aliasdecls.push(ad); + } + } + + override void visit(AttribDeclaration atb) + { + attribAddMember(atb, sc, sds); + } + + override void visit(StorageClassDeclaration stcd) + { + Dsymbols* d = stcd.include(sc); + if (d) + { + Scope* sc2 = stcd.newScope(sc); + + d.foreachDsymbol( (s) + { + //printf("\taddMember %s to %s\n", s.toChars(), sds.toChars()); + // STC.local needs to be attached before the member is added to the scope (because it influences the parent symbol) + if (auto decl = s.isDeclaration()) + { + decl.storage_class |= stcd.stc & STC.local; + if (auto sdecl = s.isStorageClassDeclaration()) // TODO: why is this not enough to deal with the nested case? + { + sdecl.stc |= stcd.stc & STC.local; + } + } + s.addMember(sc2, sds); + }); + + if (sc2 != sc) + sc2.pop(); + } + } + + override void visit(VisibilityDeclaration visd) + { + if (visd.pkg_identifiers) + { + Dsymbol tmp; + Package.resolve(visd.pkg_identifiers, &tmp, null); + visd.visibility.pkg = tmp ? tmp.isPackage() : null; + visd.pkg_identifiers = null; + } + if (visd.visibility.kind == Visibility.Kind.package_ && visd.visibility.pkg && sc._module) + { + Module m = sc._module; + + // https://issues.dlang.org/show_bug.cgi?id=17441 + // While isAncestorPackageOf does an equality check, the fix for the issue adds a check to see if + // each package's .isModule() properites are equal. + // + // Properties generated from `package(foo)` i.e. visibility.pkg have .isModule() == null. + // This breaks package declarations of the package in question if they are declared in + // the same package.d file, which _do_ have a module associated with them, and hence a non-null + // isModule() + if (!m.isPackage() || !visd.visibility.pkg.ident.equals(m.isPackage().ident)) + { + Package pkg = m.parent ? m.parent.isPackage() : null; + if (!pkg || !visd.visibility.pkg.isAncestorPackageOf(pkg)) + .error(visd.loc, "%s `%s` does not bind to one of ancestor packages of module `%s`", visd.kind(), visd.toPrettyChars(false), m.toPrettyChars(true)); + } + } + attribAddMember(visd, sc, sds); + } + + override void visit(StaticIfDeclaration sid) + { + //printf("StaticIfDeclaration::addMember() '%s'\n", sid.toChars()); + /* This is deferred until the condition evaluated later (by the include() call), + * so that expressions in the condition can refer to declarations + * in the same scope, such as: + * + * template Foo(int i) + * { + * const int j = i + 1; + * static if (j == 3) + * const int k; + * } + */ + sid.scopesym = sds; + } + + + override void visit(StaticForeachDeclaration sfd) + { + // used only for caching the enclosing symbol + sfd.scopesym = sds; + } + + /*************************************** + * Lazily initializes the scope to forward to. + */ + override void visit(ForwardingAttribDeclaration fad) + { + fad.sym.parent = sds; + sds = fad.sym; + attribAddMember(fad, sc, fad.sym); + } + + override void visit(MixinDeclaration md) + { + //printf("MixinDeclaration::addMember(sc = %p, sds = %p, memnum = %d)\n", sc, sds, md.memnum); + md.scopesym = sds; + } + + override void visit(DebugSymbol ds) + { + //printf("DebugSymbol::addMember('%s') %s\n", sds.toChars(), ds.toChars()); + Module m = sds.isModule(); + // Do not add the member to the symbol table, + // just make sure subsequent debug declarations work. + if (ds.ident) + { + if (!m) + { + .error(ds.loc, "%s `%s` declaration must be at module level", ds.kind, ds.toPrettyChars); + ds.errors = true; + } + else + { + if (findCondition(m.debugidsNot, ds.ident)) + { + .error(ds.loc, "%s `%s` defined after use", ds.kind, ds.toPrettyChars); + ds.errors = true; + } + if (!m.debugids) + m.debugids = new Identifiers(); + m.debugids.push(ds.ident); + } + } + else + { + if (!m) + { + .error(ds.loc, "%s `%s` level declaration must be at module level", ds.kind, ds.toPrettyChars); + ds.errors = true; + } + else + m.debuglevel = ds.level; + } + } + + override void visit(VersionSymbol vs) + { + //printf("VersionSymbol::addMember('%s') %s\n", sds.toChars(), vs.toChars()); + Module m = sds.isModule(); + // Do not add the member to the symbol table, + // just make sure subsequent debug declarations work. + if (vs.ident) + { + VersionCondition.checkReserved(vs.loc, vs.ident.toString()); + if (!m) + { + .error(vs.loc, "%s `%s` declaration must be at module level", vs.kind, vs.toPrettyChars); + vs.errors = true; + } + else + { + if (findCondition(m.versionidsNot, vs.ident)) + { + .error(vs.loc, "%s `%s` defined after use", vs.kind, vs.toPrettyChars); + vs.errors = true; + } + if (!m.versionids) + m.versionids = new Identifiers(); + m.versionids.push(vs.ident); + } + } + else + { + if (!m) + { + .error(vs.loc, "%s `%s` level declaration must be at module level", vs.kind, vs.toPrettyChars); + vs.errors = true; + } + else + m.versionlevel = vs.level; + } + } + + override void visit(Nspace ns) + { + visit(cast(Dsymbol)ns); + + if (ns.members) + { + if (!ns.symtab) + ns.symtab = new DsymbolTable(); + // The namespace becomes 'imported' into the enclosing scope + for (Scope* sce = sc; 1; sce = sce.enclosing) + { + ScopeDsymbol sds2 = sce.scopesym; + if (sds2) + { + sds2.importScope(ns, Visibility(Visibility.Kind.public_)); + break; + } + } + assert(sc); + sc = sc.push(ns); + sc.linkage = LINK.cpp; // namespaces default to C++ linkage + sc.parent = ns; + ns.members.foreachDsymbol(s => s.addMember(sc, ns)); + sc.pop(); + } + } + + override void visit(EnumDeclaration ed) + { + version (none) + { + printf("EnumDeclaration::addMember() %s\n", ed.toChars()); + for (size_t i = 0; i < ed.members.length; i++) + { + EnumMember em = (*ed.members)[i].isEnumMember(); + printf(" member %s\n", em.toChars()); + } + } + if (!ed.isAnonymous()) + { + visit(cast(Dsymbol)ed); + } + + addEnumMembersToSymtab(ed, sc, sds); + } +} + /******************************************* * Add members of EnumDeclaration to the symbol table(s). * Params: diff --git a/dmd/dversion.d b/dmd/dversion.d index aa22532061e..31725c80b9b 100644 --- a/dmd/dversion.d +++ b/dmd/dversion.d @@ -68,43 +68,6 @@ extern (C++) final class DebugSymbol : Dsymbol } } - override void addMember(Scope* sc, ScopeDsymbol sds) - { - //printf("DebugSymbol::addMember('%s') %s\n", sds.toChars(), toChars()); - Module m = sds.isModule(); - // Do not add the member to the symbol table, - // just make sure subsequent debug declarations work. - if (ident) - { - if (!m) - { - .error(loc, "%s `%s` declaration must be at module level", kind, toPrettyChars); - errors = true; - } - else - { - if (findCondition(m.debugidsNot, ident)) - { - .error(loc, "%s `%s` defined after use", kind, toPrettyChars); - errors = true; - } - if (!m.debugids) - m.debugids = new Identifiers(); - m.debugids.push(ident); - } - } - else - { - if (!m) - { - .error(loc, "%s `%s` level declaration must be at module level", kind, toPrettyChars); - errors = true; - } - else - m.debuglevel = level; - } - } - override const(char)* kind() const nothrow { return "debug"; @@ -162,44 +125,6 @@ extern (C++) final class VersionSymbol : Dsymbol } } - override void addMember(Scope* sc, ScopeDsymbol sds) - { - //printf("VersionSymbol::addMember('%s') %s\n", sds.toChars(), toChars()); - Module m = sds.isModule(); - // Do not add the member to the symbol table, - // just make sure subsequent debug declarations work. - if (ident) - { - VersionCondition.checkReserved(loc, ident.toString()); - if (!m) - { - .error(loc, "%s `%s` declaration must be at module level", kind, toPrettyChars); - errors = true; - } - else - { - if (findCondition(m.versionidsNot, ident)) - { - .error(loc, "%s `%s` defined after use", kind, toPrettyChars); - errors = true; - } - if (!m.versionids) - m.versionids = new Identifiers(); - m.versionids.push(ident); - } - } - else - { - if (!m) - { - .error(loc, "%s `%s` level declaration must be at module level", kind, toPrettyChars); - errors = true; - } - else - m.versionlevel = level; - } - } - override const(char)* kind() const nothrow { return "version"; diff --git a/dmd/enum.h b/dmd/enum.h index be12c65e6d6..c0bd1c68ff4 100644 --- a/dmd/enum.h +++ b/dmd/enum.h @@ -46,7 +46,6 @@ class EnumDeclaration final : public ScopeDsymbol bool inuse(bool v); EnumDeclaration *syntaxCopy(Dsymbol *s) override; - void addMember(Scope *sc, ScopeDsymbol *sds) override; void setScope(Scope *sc) override; bool oneMember(Dsymbol **ps, Identifier *ident) override; Type *getType() override; diff --git a/dmd/frontend.h b/dmd/frontend.h index 950aa92bb74..9fb712be9aa 100644 --- a/dmd/frontend.h +++ b/dmd/frontend.h @@ -47,7 +47,6 @@ class CPPNamespaceDeclaration; class UserAttributeDeclaration; class Module; class TemplateInstance; -class ScopeDsymbol; class AggregateDeclaration; class LabelDsymbol; class ClassDeclaration; @@ -90,6 +89,7 @@ class DebugSymbol; class StructDeclaration; class UnionDeclaration; class InterfaceDeclaration; +class ScopeDsymbol; class ForwardingScopeDsymbol; class WithScopeSymbol; class ArrayScopeSymbol; @@ -499,7 +499,6 @@ class Dsymbol : public ASTNode virtual const char* kind() const; virtual Dsymbol* toAlias(); virtual Dsymbol* toAlias2(); - virtual void addMember(Scope* sc, ScopeDsymbol* sds); virtual void setScope(Scope* sc); virtual void importAll(Scope* sc); virtual Dsymbol* search(const Loc& loc, Identifier* ident, int32_t flags = 0); @@ -3941,7 +3940,6 @@ class Nspace final : public ScopeDsymbol public: Expression* identExp; Nspace* syntaxCopy(Dsymbol* s) override; - void addMember(Scope* sc, ScopeDsymbol* sds) override; void setScope(Scope* sc) override; Dsymbol* search(const Loc& loc, Identifier* ident, int32_t flags = 8) override; bool hasPointers() override; @@ -4563,7 +4561,6 @@ class StaticAssert final : public Dsymbol Expression* exp; Array* msgs; StaticAssert* syntaxCopy(Dsymbol* s) override; - void addMember(Scope* sc, ScopeDsymbol* sds) override; bool oneMember(Dsymbol** ps, Identifier* ident) override; const char* kind() const override; StaticAssert* isStaticAssert() override; @@ -5389,7 +5386,6 @@ class AttribDeclaration : public Dsymbol Array* decl; virtual Array* include(Scope* sc); virtual Scope* newScope(Scope* sc); - void addMember(Scope* sc, ScopeDsymbol* sds) override; void setScope(Scope* sc) override; void importAll(Scope* sc) override; void addComment(const char* comment) override; @@ -5411,7 +5407,6 @@ class StorageClassDeclaration : public AttribDeclaration StorageClassDeclaration* syntaxCopy(Dsymbol* s) override; Scope* newScope(Scope* sc) override; bool oneMember(Dsymbol** ps, Identifier* ident) final override; - void addMember(Scope* sc, ScopeDsymbol* sds) override; StorageClassDeclaration* isStorageClassDeclaration() override; void accept(Visitor* v) override; }; @@ -5467,7 +5462,6 @@ class VisibilityDeclaration final : public AttribDeclaration _d_dynamicArray< Identifier* > pkg_identifiers; VisibilityDeclaration* syntaxCopy(Dsymbol* s) override; Scope* newScope(Scope* sc) override; - void addMember(Scope* sc, ScopeDsymbol* sds) override; const char* kind() const override; const char* toPrettyChars(bool __param_0_) override; VisibilityDeclaration* isVisibilityDeclaration() override; @@ -5533,7 +5527,6 @@ class StaticIfDeclaration final : public ConditionalDeclaration public: StaticIfDeclaration* syntaxCopy(Dsymbol* s) override; Array* include(Scope* sc) override; - void addMember(Scope* sc, ScopeDsymbol* sds) override; void setScope(Scope* sc) override; void importAll(Scope* sc) override; const char* kind() const override; @@ -5552,7 +5545,6 @@ class StaticForeachDeclaration final : public AttribDeclaration StaticForeachDeclaration* syntaxCopy(Dsymbol* s) override; bool oneMember(Dsymbol** ps, Identifier* ident) override; Array* include(Scope* sc) override; - void addMember(Scope* sc, ScopeDsymbol* sds) override; void addComment(const char* comment) override; void setScope(Scope* sc) override; void importAll(Scope* sc) override; @@ -5566,7 +5558,6 @@ class ForwardingAttribDeclaration final : public AttribDeclaration ForwardingScopeDsymbol* sym; ForwardingAttribDeclaration(Array* decl); Scope* newScope(Scope* sc) override; - void addMember(Scope* sc, ScopeDsymbol* sds) override; ForwardingAttribDeclaration* isForwardingAttribDeclaration() override; void accept(Visitor* v) override; }; @@ -5578,7 +5569,6 @@ class MixinDeclaration final : public AttribDeclaration ScopeDsymbol* scopesym; bool compiled; MixinDeclaration* syntaxCopy(Dsymbol* s) override; - void addMember(Scope* sc, ScopeDsymbol* sds) override; void setScope(Scope* sc) override; const char* kind() const override; MixinDeclaration* isMixinDeclaration() override; @@ -6142,7 +6132,6 @@ class EnumDeclaration final : public ScopeDsymbol uint8_t bitFields; public: EnumDeclaration* syntaxCopy(Dsymbol* s) override; - void addMember(Scope* sc, ScopeDsymbol* sds) override; void setScope(Scope* sc) override; bool oneMember(Dsymbol** ps, Identifier* ident) override; Type* getType() override; @@ -6189,7 +6178,6 @@ class Import final : public Dsymbol Import* syntaxCopy(Dsymbol* s) override; void importAll(Scope* sc) override; Dsymbol* toAlias() override; - void addMember(Scope* sc, ScopeDsymbol* sd) override; void setScope(Scope* sc) override; Dsymbol* search(const Loc& loc, Identifier* ident, int32_t flags = 8) override; bool overloadInsert(Dsymbol* s) override; @@ -6601,6 +6589,8 @@ class DsymbolTable final : public RootObject extern void dsymbolSemantic(Dsymbol* dsym, Scope* sc); +extern void addMember(Dsymbol* dsym, Scope* sc, ScopeDsymbol* sds); + extern Expression* isExpression(RootObject* o); extern Dsymbol* isDsymbol(RootObject* o); @@ -6840,7 +6830,6 @@ class DebugSymbol final : public Dsymbol uint32_t level; DebugSymbol* syntaxCopy(Dsymbol* s) override; const char* toChars() const override; - void addMember(Scope* sc, ScopeDsymbol* sds) override; const char* kind() const override; DebugSymbol* isDebugSymbol() override; void accept(Visitor* v) override; @@ -6852,7 +6841,6 @@ class VersionSymbol final : public Dsymbol uint32_t level; VersionSymbol* syntaxCopy(Dsymbol* s) override; const char* toChars() const override; - void addMember(Scope* sc, ScopeDsymbol* sds) override; const char* kind() const override; VersionSymbol* isVersionSymbol() override; void accept(Visitor* v) override; diff --git a/dmd/import.h b/dmd/import.h index 31ee61a65fb..cc760e510e1 100644 --- a/dmd/import.h +++ b/dmd/import.h @@ -43,7 +43,6 @@ class Import final : public Dsymbol Import *syntaxCopy(Dsymbol *s) override; // copy only syntax trees void importAll(Scope *sc) override; Dsymbol *toAlias() override; - void addMember(Scope *sc, ScopeDsymbol *sds) override; void setScope(Scope* sc) override; Dsymbol *search(const Loc &loc, Identifier *ident, int flags = SearchLocalsOnly) override; bool overloadInsert(Dsymbol *s) override; diff --git a/dmd/nspace.d b/dmd/nspace.d index 2d3367af804..08b76db255e 100644 --- a/dmd/nspace.d +++ b/dmd/nspace.d @@ -85,33 +85,6 @@ extern (C++) final class Nspace : ScopeDsymbol return ns; } - override void addMember(Scope* sc, ScopeDsymbol sds) - { - ScopeDsymbol.addMember(sc, sds); - - if (members) - { - if (!symtab) - symtab = new DsymbolTable(); - // The namespace becomes 'imported' into the enclosing scope - for (Scope* sce = sc; 1; sce = sce.enclosing) - { - ScopeDsymbol sds2 = sce.scopesym; - if (sds2) - { - sds2.importScope(this, Visibility(Visibility.Kind.public_)); - break; - } - } - assert(sc); - sc = sc.push(this); - sc.linkage = LINK.cpp; // namespaces default to C++ linkage - sc.parent = this; - members.foreachDsymbol(s => s.addMember(sc, this)); - sc.pop(); - } - } - override void setScope(Scope* sc) { ScopeDsymbol.setScope(sc); diff --git a/dmd/nspace.h b/dmd/nspace.h index e9fb7bdc777..500816425ae 100644 --- a/dmd/nspace.h +++ b/dmd/nspace.h @@ -21,7 +21,6 @@ class Nspace final : public ScopeDsymbol public: Expression *identExp; Nspace *syntaxCopy(Dsymbol *s) override; - void addMember(Scope *sc, ScopeDsymbol *sds) override; void setScope(Scope *sc) override; Dsymbol *search(const Loc &loc, Identifier *ident, int flags = SearchLocalsOnly) override; bool hasPointers() override; diff --git a/dmd/staticassert.d b/dmd/staticassert.d index 15c46b304ba..7f22c4c993a 100644 --- a/dmd/staticassert.d +++ b/dmd/staticassert.d @@ -52,11 +52,6 @@ extern (C++) final class StaticAssert : Dsymbol return new StaticAssert(loc, exp.syntaxCopy(), msgs ? Expression.arraySyntaxCopy(msgs) : null); } - override void addMember(Scope* sc, ScopeDsymbol sds) - { - // we didn't add anything - } - override bool oneMember(Dsymbol* ps, Identifier ident) { //printf("StaticAssert::oneMember())\n"); diff --git a/dmd/staticassert.h b/dmd/staticassert.h index 2b7d300f6af..c0d5363a414 100644 --- a/dmd/staticassert.h +++ b/dmd/staticassert.h @@ -21,7 +21,6 @@ class StaticAssert : public Dsymbol Expressions *msg; StaticAssert *syntaxCopy(Dsymbol *s) override; - void addMember(Scope *sc, ScopeDsymbol *sds) override; bool oneMember(Dsymbol **ps, Identifier *ident) override; const char *kind() const override; StaticAssert *isStaticAssert() override { return this; } diff --git a/dmd/version.h b/dmd/version.h index 697d46ee211..c268bc9b8cf 100644 --- a/dmd/version.h +++ b/dmd/version.h @@ -20,7 +20,6 @@ class DebugSymbol final : public Dsymbol DebugSymbol *syntaxCopy(Dsymbol *) override; const char *toChars() const override; - void addMember(Scope *sc, ScopeDsymbol *sds) override; const char *kind() const override; DebugSymbol *isDebugSymbol() override; void accept(Visitor *v) override { v->visit(this); } @@ -34,7 +33,6 @@ class VersionSymbol final : public Dsymbol VersionSymbol *syntaxCopy(Dsymbol *) override; const char *toChars() const override; - void addMember(Scope *sc, ScopeDsymbol *sds) override; const char *kind() const override; VersionSymbol *isVersionSymbol() override; void accept(Visitor *v) override { v->visit(this); } From ee170ed8ff315bd99441bb2831422547e38b8a9a Mon Sep 17 00:00:00 2001 From: Nick Treleaven Date: Fri, 17 Nov 2023 20:42:54 +0000 Subject: [PATCH 053/215] Also show argument types --- dmd/func.d | 11 +++++++++-- tests/dmd/fail_compilation/ctor_attr.d | 2 +- tests/dmd/fail_compilation/testrvaluecpctor.d | 2 +- 3 files changed, 11 insertions(+), 4 deletions(-) diff --git a/dmd/func.d b/dmd/func.d index 05e4f56c9e7..06b171506f5 100644 --- a/dmd/func.d +++ b/dmd/func.d @@ -3422,8 +3422,15 @@ FuncDeclaration resolveFuncCall(const ref Loc loc, Scope* sc, Dsymbol s, auto mismatches = MODMatchToBuffer(&funcBuf, tf.mod, tthis.mod); if (hasOverloads) { - .error(loc, "none of the overloads of `%s` are callable using a %sobject", - fd.toChars(), thisBuf.peekChars()); + OutBuffer buf; + buf.argExpTypesToCBuffer(fargs); + if (fd.isCtorDeclaration()) + .error(loc, "none of the overloads of `%s` can construct a %sobject with argument types `(%s)`", + fd.toChars(), thisBuf.peekChars(), buf.peekChars()); + else + .error(loc, "none of the overloads of `%s` are callable using a %sobject", + fd.toChars(), thisBuf.peekChars()); + if (!global.gag || global.params.v.showGaggedErrors) printCandidates(loc, fd, sc.isDeprecated()); return null; diff --git a/tests/dmd/fail_compilation/ctor_attr.d b/tests/dmd/fail_compilation/ctor_attr.d index bdaf4e686d6..6acc300aa38 100644 --- a/tests/dmd/fail_compilation/ctor_attr.d +++ b/tests/dmd/fail_compilation/ctor_attr.d @@ -1,7 +1,7 @@ /* TEST_OUTPUT: --- -fail_compilation/ctor_attr.d(26): Error: none of the overloads of `this` are callable using a mutable object +fail_compilation/ctor_attr.d(26): Error: none of the overloads of `this` can construct a mutable object with argument types `(int)` fail_compilation/ctor_attr.d(16): Candidates are: `ctor_attr.S.this(int x) const` fail_compilation/ctor_attr.d(18): `ctor_attr.S.this(string x)` fail_compilation/ctor_attr.d(17): `this()(int x) shared` diff --git a/tests/dmd/fail_compilation/testrvaluecpctor.d b/tests/dmd/fail_compilation/testrvaluecpctor.d index 93cf52aabc4..1173d14480d 100644 --- a/tests/dmd/fail_compilation/testrvaluecpctor.d +++ b/tests/dmd/fail_compilation/testrvaluecpctor.d @@ -5,7 +5,7 @@ TEST_OUTPUT: --- fail_compilation/testrvaluecpctor.d(16): Error: cannot define both an rvalue constructor and a copy constructor for `struct Foo` fail_compilation/testrvaluecpctor.d(24): Template instance `testrvaluecpctor.Foo!int.Foo.__ctor!(immutable(Foo!int), immutable(Foo!int))` creates an rvalue constructor for `struct Foo` -fail_compilation/testrvaluecpctor.d(24): Error: none of the overloads of `this` are callable using a `immutable` object +fail_compilation/testrvaluecpctor.d(24): Error: none of the overloads of `this` can construct a `immutable` object with argument types `(immutable(Foo!int))` fail_compilation/testrvaluecpctor.d(18): Candidates are: `testrvaluecpctor.Foo!int.Foo.this(ref scope Foo!int rhs)` fail_compilation/testrvaluecpctor.d(16): `this(Rhs, this This)(scope Rhs rhs)` --- From 8f968a70d1e9805fd5687e9ce177bf5e53ca7a7f Mon Sep 17 00:00:00 2001 From: Razvan Nitu Date: Sun, 19 Nov 2023 00:39:57 +0200 Subject: [PATCH 054/215] Extract Dsymbol.search from dsymbols.d and transform it into a visitor (dlang/dmd!15787) --- dmd/aggregate.d | 2 +- dmd/aggregate.h | 2 - dmd/dclass.d | 67 +-- dmd/declaration.d | 12 - dmd/declaration.h | 1 - dmd/denum.d | 13 - dmd/dimport.d | 13 - dmd/dmodule.d | 65 +-- dmd/dstruct.d | 17 - dmd/dsymbol.d | 407 +---------------- dmd/dsymbol.h | 11 +- dmd/dsymbolsem.d | 614 ++++++++++++++++++++++++++ dmd/dtoh.d | 1 + dmd/enum.h | 1 - dmd/frontend.h | 22 +- dmd/import.h | 1 - dmd/importc.d | 1 + dmd/initsem.d | 1 + dmd/lambdacomp.d | 1 + dmd/module.h | 2 - dmd/nspace.d | 16 - dmd/nspace.h | 1 - dmd/opover.d | 1 + tests/dmd/unit/compilable/searching.d | 1 + 24 files changed, 640 insertions(+), 633 deletions(-) diff --git a/dmd/aggregate.d b/dmd/aggregate.d index d42ef951085..307bb0171c4 100644 --- a/dmd/aggregate.d +++ b/dmd/aggregate.d @@ -663,7 +663,7 @@ extern (C++) abstract class AggregateDeclaration : ScopeDsymbol */ extern (D) final Dsymbol searchCtor() { - auto s = search(Loc.initial, Id.ctor); + auto s = this.search(Loc.initial, Id.ctor); if (s) { if (!(s.isCtorDeclaration() || diff --git a/dmd/aggregate.h b/dmd/aggregate.h index 58a0126de1a..cd8f1a15fbd 100644 --- a/dmd/aggregate.h +++ b/dmd/aggregate.h @@ -167,7 +167,6 @@ class StructDeclaration : public AggregateDeclaration public: static StructDeclaration *create(const Loc &loc, Identifier *id, bool inObject); StructDeclaration *syntaxCopy(Dsymbol *s) override; - Dsymbol *search(const Loc &loc, Identifier *ident, int flags = SearchLocalsOnly) override final; const char *kind() const override; void finalizeSize() override final; bool isPOD(); @@ -285,7 +284,6 @@ class ClassDeclaration : public AggregateDeclaration virtual bool isBaseOf(ClassDeclaration *cd, int *poffset); bool isBaseInfoComplete(); - Dsymbol *search(const Loc &loc, Identifier *ident, int flags = SearchLocalsOnly) override final; void finalizeSize() override; bool hasMonitor(); bool isFuncHidden(FuncDeclaration *fd); diff --git a/dmd/dclass.d b/dmd/dclass.d index bae942cbd97..72b85cfc64e 100644 --- a/dmd/dclass.d +++ b/dmd/dclass.d @@ -180,7 +180,7 @@ extern (C++) class ClassDeclaration : AggregateDeclaration int cppDtorVtblIndex = -1; /// to prevent recursive attempts - private bool inuse; + bool inuse; ThreeState isabstract; @@ -367,7 +367,7 @@ extern (C++) class ClassDeclaration : AggregateDeclaration baseok = Baseok.none; } - extern (D) private void classError(const(char)* fmt, const(char)* arg) + extern (D) final void classError(const(char)* fmt, const(char)* arg) { .error(loc, fmt, kind, toPrettyChars, arg); } @@ -468,67 +468,6 @@ extern (C++) class ClassDeclaration : AggregateDeclaration return baseok >= Baseok.done; } - override final Dsymbol search(const ref Loc loc, Identifier ident, int flags = SearchLocalsOnly) - { - //printf("%s.ClassDeclaration.search('%s', flags=x%x)\n", toChars(), ident.toChars(), flags); - //if (_scope) printf("%s baseok = %d\n", toChars(), baseok); - if (_scope && baseok < Baseok.semanticdone) - { - if (!inuse) - { - // must semantic on base class/interfaces - inuse = true; - dsymbolSemantic(this, null); - inuse = false; - } - } - - if (!members || !symtab) // opaque or addMember is not yet done - { - // .stringof is always defined (but may be hidden by some other symbol) - if (ident != Id.stringof && !(flags & IgnoreErrors) && semanticRun < PASS.semanticdone) - classError("%s `%s` is forward referenced when looking for `%s`", ident.toChars()); - //*(char*)0=0; - return null; - } - - auto s = ScopeDsymbol.search(loc, ident, flags); - - // don't search imports of base classes - if (flags & SearchImportsOnly) - return s; - - if (s) - return s; - - // Search bases classes in depth-first, left to right order - foreach (b; (*baseclasses)[]) - { - if (!b.sym) - continue; - - if (!b.sym.symtab) - { - classError("%s `%s` base `%s` is forward referenced", b.sym.ident.toChars()); - continue; - } - - import dmd.access : symbolIsVisible; - - s = b.sym.search(loc, ident, flags); - if (!s) - continue; - else if (s == this) // happens if s is nested in this and derives from this - s = null; - else if (!(flags & IgnoreSymbolVisibility) && !(s.visible().kind == Visibility.Kind.protected_) && !symbolIsVisible(this, s)) - s = null; - else - break; - } - - return s; - } - /************************************ * Search base classes in depth-first, left-to-right order for * a class or interface named 'ident'. @@ -675,7 +614,7 @@ extern (C++) class ClassDeclaration : AggregateDeclaration final bool isFuncHidden(FuncDeclaration fd) { //printf("ClassDeclaration.isFuncHidden(class = %s, fd = %s)\n", toChars(), fd.toPrettyChars()); - Dsymbol s = search(Loc.initial, fd.ident, IgnoreAmbiguous | IgnoreErrors); + Dsymbol s = this.search(Loc.initial, fd.ident, IgnoreAmbiguous | IgnoreErrors); if (!s) { //printf("not found\n"); diff --git a/dmd/declaration.d b/dmd/declaration.d index 76a31f4caf7..0e125fdd001 100644 --- a/dmd/declaration.d +++ b/dmd/declaration.d @@ -421,18 +421,6 @@ extern (C++) abstract class Declaration : Dsymbol return Modifiable.yes; } - override final Dsymbol search(const ref Loc loc, Identifier ident, int flags = SearchLocalsOnly) - { - Dsymbol s = Dsymbol.search(loc, ident, flags); - if (!s && type) - { - s = type.toDsymbol(_scope); - if (s) - s = s.search(loc, ident, flags); - } - return s; - } - final bool isStatic() const pure nothrow @nogc @safe { return (storage_class & STC.static_) != 0; diff --git a/dmd/declaration.h b/dmd/declaration.h index 8cd295f1e06..a65fb4467e5 100644 --- a/dmd/declaration.h +++ b/dmd/declaration.h @@ -124,7 +124,6 @@ class Declaration : public Dsymbol const char *kind() const override; uinteger_t size(const Loc &loc) override final; - Dsymbol *search(const Loc &loc, Identifier *ident, int flags = SearchLocalsOnly) override final; bool isStatic() const { return (storage_class & STCstatic) != 0; } LINK resolvedLinkage() const; // returns the linkage, resolving the target-specific `System` one diff --git a/dmd/denum.d b/dmd/denum.d index 17ec7fb194b..797f6ee0a2d 100644 --- a/dmd/denum.d +++ b/dmd/denum.d @@ -107,19 +107,6 @@ extern (C++) final class EnumDeclaration : ScopeDsymbol return "enum"; } - override Dsymbol search(const ref Loc loc, Identifier ident, int flags = SearchLocalsOnly) - { - //printf("%s.EnumDeclaration::search('%s')\n", toChars(), ident.toChars()); - if (_scope) - { - // Try one last time to resolve this enum - dsymbolSemantic(this, _scope); - } - - Dsymbol s = ScopeDsymbol.search(loc, ident, flags); - return s; - } - // is Dsymbol deprecated? override bool isDeprecated() const { diff --git a/dmd/dimport.d b/dmd/dimport.d index 7c1c9319de5..0132e49cbed 100644 --- a/dmd/dimport.d +++ b/dmd/dimport.d @@ -321,19 +321,6 @@ extern (C++) final class Import : Dsymbol } } - override Dsymbol search(const ref Loc loc, Identifier ident, int flags = SearchLocalsOnly) - { - //printf("%s.Import.search(ident = '%s', flags = x%x)\n", toChars(), ident.toChars(), flags); - if (!pkg) - { - load(null); - mod.importAll(null); - mod.dsymbolSemantic(null); - } - // Forward it to the package/module - return pkg.search(loc, ident, flags); - } - override bool overloadInsert(Dsymbol s) { /* Allow multiple imports with the same package base, but disallow diff --git a/dmd/dmodule.d b/dmd/dmodule.d index e6dde181fab..5f5de6390fb 100644 --- a/dmd/dmodule.d +++ b/dmd/dmodule.d @@ -268,22 +268,6 @@ extern (C++) class Package : ScopeDsymbol return isAncestorPackageOf(pkg.parent.isPackage()); } - override Dsymbol search(const ref Loc loc, Identifier ident, int flags = SearchLocalsOnly) - { - //printf("%s Package.search('%s', flags = x%x)\n", toChars(), ident.toChars(), flags); - flags &= ~SearchLocalsOnly; // searching an import is always transitive - if (!isModule() && mod) - { - // Prefer full package name. - Dsymbol s = symtab ? symtab.lookup(ident) : null; - if (s) - return s; - //printf("[%s] through pkdmod: %s\n", loc.toChars(), toChars()); - return mod.search(loc, ident, flags); - } - return ScopeDsymbol.search(loc, ident, flags); - } - override void accept(Visitor v) { v.visit(this); @@ -414,10 +398,10 @@ extern (C++) final class Module : Package return rootimports == ThreeState.yes; } - private Identifier searchCacheIdent; - private Dsymbol searchCacheSymbol; // cached value of search - private int searchCacheFlags; // cached flags - private bool insearch; + Identifier searchCacheIdent; + Dsymbol searchCacheSymbol; // cached value of search + int searchCacheFlags; // cached flags + bool insearch; /** * A root module is one that will be compiled all the way to @@ -1036,47 +1020,6 @@ extern (C++) final class Module : Package } } - override Dsymbol search(const ref Loc loc, Identifier ident, int flags = SearchLocalsOnly) - { - /* Since modules can be circularly referenced, - * need to stop infinite recursive searches. - * This is done with the cache. - */ - //printf("%s Module.search('%s', flags = x%x) insearch = %d\n", toChars(), ident.toChars(), flags, insearch); - if (insearch) - return null; - - /* Qualified module searches always search their imports, - * even if SearchLocalsOnly - */ - if (!(flags & SearchUnqualifiedModule)) - flags &= ~(SearchUnqualifiedModule | SearchLocalsOnly); - - if (searchCacheIdent == ident && searchCacheFlags == flags) - { - //printf("%s Module::search('%s', flags = %d) insearch = %d searchCacheSymbol = %s\n", - // toChars(), ident.toChars(), flags, insearch, searchCacheSymbol ? searchCacheSymbol.toChars() : "null"); - return searchCacheSymbol; - } - - uint errors = global.errors; - - insearch = true; - Dsymbol s = ScopeDsymbol.search(loc, ident, flags); - insearch = false; - - if (errors == global.errors) - { - // https://issues.dlang.org/show_bug.cgi?id=10752 - // Can cache the result only when it does not cause - // access error so the side-effect should be reproduced in later search. - searchCacheIdent = ident; - searchCacheSymbol = s; - searchCacheFlags = flags; - } - return s; - } - override bool isPackageAccessible(Package p, Visibility visibility, int flags = 0) { if (insearch) // don't follow import cycles diff --git a/dmd/dstruct.d b/dmd/dstruct.d index f77a263a894..36e847c3f88 100644 --- a/dmd/dstruct.d +++ b/dmd/dstruct.d @@ -263,23 +263,6 @@ extern (C++) class StructDeclaration : AggregateDeclaration return sd; } - override final Dsymbol search(const ref Loc loc, Identifier ident, int flags = SearchLocalsOnly) - { - //printf("%s.StructDeclaration::search('%s', flags = x%x)\n", toChars(), ident.toChars(), flags); - if (_scope && !symtab) - dsymbolSemantic(this, _scope); - - if (!members || !symtab) // opaque or semantic() is not yet called - { - // .stringof is always defined (but may be hidden by some other symbol) - if(ident != Id.stringof && !(flags & IgnoreErrors) && semanticRun < PASS.semanticdone) - .error(loc, "%s `%s` is forward referenced when looking for `%s`", kind, toPrettyChars, ident.toChars()); - return null; - } - - return ScopeDsymbol.search(loc, ident, flags); - } - override const(char)* kind() const { return "struct"; diff --git a/dmd/dsymbol.d b/dmd/dsymbol.d index 1f3801cd094..35c36fb6de5 100644 --- a/dmd/dsymbol.d +++ b/dmd/dsymbol.d @@ -35,7 +35,6 @@ import dmd.dsymbolsem; import dmd.dtemplate; import dmd.errors; import dmd.expression; -import dmd.expressionsem; import dmd.func; import dmd.globals; import dmd.id; @@ -769,21 +768,6 @@ extern (C++) class Dsymbol : ASTNode { } - /********************************************* - * Search for ident as member of s. - * Params: - * loc = location to print for error messages - * ident = identifier to search for - * flags = IgnoreXXXX - * Returns: - * null if not found - */ - Dsymbol search(const ref Loc loc, Identifier ident, int flags = IgnoreNone) - { - //printf("Dsymbol::search(this=%p,%s, ident='%s')\n", this, toChars(), ident.toChars()); - return null; - } - extern (D) final Dsymbol search_correct(Identifier ident) { /*************************************************** @@ -808,7 +792,7 @@ extern (C++) class Dsymbol : ASTNode if (global.gag) return null; // don't do it for speculative compiles; too time consuming // search for exact name first - if (auto s = search(Loc.initial, ident, IgnoreErrors)) + if (auto s = this.search(Loc.initial, ident, IgnoreErrors)) return s; return speller!symbol_search_fp(ident.toString()); } @@ -1219,12 +1203,12 @@ extern (C++) class ScopeDsymbol : Dsymbol Dsymbols* members; // all Dsymbol's in this scope DsymbolTable symtab; // members[] sorted into table uint endlinnum; // the linnumber of the statement after the scope (0 if unknown) - -private: /// symbols whose members have been imported, i.e. imported modules and template mixins Dsymbols* importedScopes; Visibility.Kind* visibilities; // array of Visibility.Kind, one for each import +private: + import dmd.root.bitarray; BitArray accessiblePackages, privateAccessiblePackages;// whitelists of accessible (imported) packages @@ -1253,166 +1237,7 @@ public: return sds; } - /***************************************** - * This function is #1 on the list of functions that eat cpu time. - * Be very, very careful about slowing it down. - */ - override Dsymbol search(const ref Loc loc, Identifier ident, int flags = SearchLocalsOnly) - { - //printf("%s.ScopeDsymbol::search(ident='%s', flags=x%x)\n", toChars(), ident.toChars(), flags); - //if (strcmp(ident.toChars(),"c") == 0) *(char*)0=0; - - // Look in symbols declared in this module - if (symtab && !(flags & SearchImportsOnly)) - { - //printf(" look in locals\n"); - auto s1 = symtab.lookup(ident); - if (s1) - { - //printf("\tfound in locals = '%s.%s'\n",toChars(),s1.toChars()); - return s1; - } - } - //printf(" not found in locals\n"); - - // Look in imported scopes - if (!importedScopes) - return null; - - //printf(" look in imports\n"); - Dsymbol s = null; - OverloadSet a = null; - // Look in imported modules - for (size_t i = 0; i < importedScopes.length; i++) - { - // If private import, don't search it - if ((flags & IgnorePrivateImports) && visibilities[i] == Visibility.Kind.private_) - continue; - int sflags = flags & (IgnoreErrors | IgnoreAmbiguous); // remember these in recursive searches - Dsymbol ss = (*importedScopes)[i]; - //printf("\tscanning import '%s', visibilities = %d, isModule = %p, isImport = %p\n", ss.toChars(), visibilities[i], ss.isModule(), ss.isImport()); - - if (ss.isModule()) - { - if (flags & SearchLocalsOnly) - continue; - } - else // mixin template - { - if (flags & SearchImportsOnly) - continue; - - sflags |= SearchLocalsOnly; - } - - /* Don't find private members if ss is a module - */ - Dsymbol s2 = ss.search(loc, ident, sflags | (ss.isModule() ? IgnorePrivateImports : IgnoreNone)); - import dmd.access : symbolIsVisible; - if (!s2 || !(flags & IgnoreSymbolVisibility) && !symbolIsVisible(this, s2)) - continue; - if (!s) - { - s = s2; - if (s && s.isOverloadSet()) - a = mergeOverloadSet(ident, a, s); - } - else if (s2 && s != s2) - { - if (s.toAlias() == s2.toAlias() || s.getType() == s2.getType() && s.getType()) - { - /* After following aliases, we found the same - * symbol, so it's not an ambiguity. But if one - * alias is deprecated or less accessible, prefer - * the other. - */ - if (s.isDeprecated() || s.visible() < s2.visible() && s2.visible().kind != Visibility.Kind.none) - s = s2; - } - else - { - /* Two imports of the same module should be regarded as - * the same. - */ - Import i1 = s.isImport(); - Import i2 = s2.isImport(); - if (!(i1 && i2 && (i1.mod == i2.mod || (!i1.parent.isImport() && !i2.parent.isImport() && i1.ident.equals(i2.ident))))) - { - /* https://issues.dlang.org/show_bug.cgi?id=8668 - * Public selective import adds AliasDeclaration in module. - * To make an overload set, resolve aliases in here and - * get actual overload roots which accessible via s and s2. - */ - s = s.toAlias(); - s2 = s2.toAlias(); - /* If both s2 and s are overloadable (though we only - * need to check s once) - */ - - auto so2 = s2.isOverloadSet(); - if ((so2 || s2.isOverloadable()) && (a || s.isOverloadable())) - { - if (symbolIsVisible(this, s2)) - { - a = mergeOverloadSet(ident, a, s2); - } - if (!symbolIsVisible(this, s)) - s = s2; - continue; - } - - /* Two different overflow sets can have the same members - * https://issues.dlang.org/show_bug.cgi?id=16709 - */ - auto so = s.isOverloadSet(); - if (so && so2) - { - if (so.a.length == so2.a.length) - { - foreach (j; 0 .. so.a.length) - { - if (so.a[j] !is so2.a[j]) - goto L1; - } - continue; // the same - L1: - { } // different - } - } - - if (flags & IgnoreAmbiguous) // if return NULL on ambiguity - return null; - - /* If two imports from C import files, pick first one, as C has global name space - */ - if (s.isCsymbol() && s2.isCsymbol()) - continue; - - if (!(flags & IgnoreErrors)) - ScopeDsymbol.multiplyDefined(loc, s, s2); - break; - } - } - } - } - if (s) - { - /* Build special symbol if we had multiple finds - */ - if (a) - { - if (!s.isOverloadSet()) - a = mergeOverloadSet(ident, a, s); - s = a; - } - //printf("\tfound in imports %s.%s\n", toChars(), s.toChars()); - return s; - } - //printf(" not found in imports\n"); - return null; - } - - extern (D) private OverloadSet mergeOverloadSet(Identifier ident, OverloadSet os, Dsymbol s) + extern (D) final OverloadSet mergeOverloadSet(Identifier ident, OverloadSet os, Dsymbol s) { if (!os) { @@ -1692,40 +1517,6 @@ extern (C++) final class WithScopeSymbol : ScopeDsymbol this.withstate = withstate; } - override Dsymbol search(const ref Loc loc, Identifier ident, int flags = SearchLocalsOnly) - { - //printf("WithScopeSymbol.search(%s)\n", ident.toChars()); - if (flags & SearchImportsOnly) - return null; - // Acts as proxy to the with class declaration - Dsymbol s = null; - Expression eold = null; - for (Expression e = withstate.exp; e && e != eold; e = resolveAliasThis(_scope, e, true)) - { - if (auto se = e.isScopeExp()) - { - s = se.sds; - } - else if (e.isTypeExp()) - { - s = e.type.toDsymbol(null); - } - else - { - Type t = e.type.toBasetype(); - s = t.toDsymbol(null); - } - if (s) - { - s = s.search(loc, ident, flags); - if (s) - return s; - } - eold = e; - } - return null; - } - override inout(WithScopeSymbol) isWithScopeSymbol() inout { return this; @@ -1744,7 +1535,7 @@ extern (C++) final class ArrayScopeSymbol : ScopeDsymbol { // either a SliceExp, an IndexExp, an ArrayExp, a TypeTuple or a TupleDeclaration. // Discriminated using DYNCAST and, for expressions, also EXP - private RootObject arrayContent; + RootObject arrayContent; extern (D) this(Scope* sc, Expression exp) nothrow @safe { @@ -1766,194 +1557,6 @@ extern (C++) final class ArrayScopeSymbol : ScopeDsymbol this.arrayContent = td; } - /// This override is used to solve `$` - override Dsymbol search(const ref Loc loc, Identifier ident, int flags = IgnoreNone) - { - //printf("ArrayScopeSymbol::search('%s', flags = %d)\n", ident.toChars(), flags); - if (ident != Id.dollar) - return null; - - VarDeclaration* pvar; - Expression ce; - - static Dsymbol dollarFromTypeTuple(const ref Loc loc, TypeTuple tt, Scope* sc) - { - - /* $ gives the number of type entries in the type tuple - */ - auto v = new VarDeclaration(loc, Type.tsize_t, Id.dollar, null); - Expression e = new IntegerExp(Loc.initial, tt.arguments.length, Type.tsize_t); - v._init = new ExpInitializer(Loc.initial, e); - v.storage_class |= STC.temp | STC.static_ | STC.const_; - v.dsymbolSemantic(sc); - return v; - } - - const DYNCAST kind = arrayContent.dyncast(); - switch (kind) with (DYNCAST) - { - case dsymbol: - TupleDeclaration td = cast(TupleDeclaration) arrayContent; - /* $ gives the number of elements in the tuple - */ - auto v = new VarDeclaration(loc, Type.tsize_t, Id.dollar, null); - Expression e = new IntegerExp(Loc.initial, td.objects.length, Type.tsize_t); - v._init = new ExpInitializer(Loc.initial, e); - v.storage_class |= STC.temp | STC.static_ | STC.const_; - v.dsymbolSemantic(_scope); - return v; - case type: - return dollarFromTypeTuple(loc, cast(TypeTuple) arrayContent, _scope); - default: - break; - } - Expression exp = cast(Expression) arrayContent; - if (auto ie = exp.isIndexExp()) - { - /* array[index] where index is some function of $ - */ - pvar = &ie.lengthVar; - ce = ie.e1; - } - else if (auto se = exp.isSliceExp()) - { - /* array[lwr .. upr] where lwr or upr is some function of $ - */ - pvar = &se.lengthVar; - ce = se.e1; - } - else if (auto ae = exp.isArrayExp()) - { - /* array[e0, e1, e2, e3] where e0, e1, e2 are some function of $ - * $ is a opDollar!(dim)() where dim is the dimension(0,1,2,...) - */ - pvar = &ae.lengthVar; - ce = ae.e1; - } - else - { - /* Didn't find $, look in enclosing scope(s). - */ - return null; - } - ce = ce.lastComma(); - /* If we are indexing into an array that is really a type - * tuple, rewrite this as an index into a type tuple and - * try again. - */ - if (auto te = ce.isTypeExp()) - { - if (auto ttp = te.type.isTypeTuple()) - return dollarFromTypeTuple(loc, ttp, _scope); - } - /* *pvar is lazily initialized, so if we refer to $ - * multiple times, it gets set only once. - */ - if (!*pvar) // if not already initialized - { - /* Create variable v and set it to the value of $ - */ - VarDeclaration v; - Type t; - if (auto tupexp = ce.isTupleExp()) - { - /* It is for an expression tuple, so the - * length will be a const. - */ - Expression e = new IntegerExp(Loc.initial, tupexp.exps.length, Type.tsize_t); - v = new VarDeclaration(loc, Type.tsize_t, Id.dollar, new ExpInitializer(Loc.initial, e)); - v.storage_class |= STC.temp | STC.static_ | STC.const_; - } - else if (ce.type && (t = ce.type.toBasetype()) !is null && (t.ty == Tstruct || t.ty == Tclass)) - { - // Look for opDollar - assert(exp.op == EXP.array || exp.op == EXP.slice); - AggregateDeclaration ad = isAggregate(t); - assert(ad); - Dsymbol s = ad.search(loc, Id.opDollar); - if (!s) // no dollar exists -- search in higher scope - return null; - s = s.toAlias(); - Expression e = null; - // Check for multi-dimensional opDollar(dim) template. - if (TemplateDeclaration td = s.isTemplateDeclaration()) - { - dinteger_t dim = 0; - if (auto ae = exp.isArrayExp()) - { - dim = ae.currentDimension; - } - else if (exp.isSliceExp()) - { - dim = 0; // slices are currently always one-dimensional - } - else - { - assert(0); - } - auto tiargs = new Objects(); - Expression edim = new IntegerExp(Loc.initial, dim, Type.tsize_t); - edim = edim.expressionSemantic(_scope); - tiargs.push(edim); - e = new DotTemplateInstanceExp(loc, ce, td.ident, tiargs); - } - else - { - /* opDollar exists, but it's not a template. - * This is acceptable ONLY for single-dimension indexing. - * Note that it's impossible to have both template & function opDollar, - * because both take no arguments. - */ - auto ae = exp.isArrayExp(); - if (ae && ae.arguments.length != 1) - { - error(exp.loc, "`%s` only defines opDollar for one dimension", ad.toChars()); - return null; - } - Declaration d = s.isDeclaration(); - assert(d); - e = new DotVarExp(loc, ce, d); - } - e = e.expressionSemantic(_scope); - if (!e.type) - error(exp.loc, "`%s` has no value", e.toChars()); - t = e.type.toBasetype(); - if (t && t.ty == Tfunction) - e = new CallExp(e.loc, e); - v = new VarDeclaration(loc, null, Id.dollar, new ExpInitializer(Loc.initial, e)); - v.storage_class |= STC.temp | STC.ctfe | STC.rvalue; - } - else - { - /* For arrays, $ will either be a compile-time constant - * (in which case its value in set during constant-folding), - * or a variable (in which case an expression is created in - * toir.c). - */ - - // https://issues.dlang.org/show_bug.cgi?id=16213 - // For static arrays $ is known at compile time, - // so declare it as a manifest constant. - auto tsa = ce.type ? ce.type.isTypeSArray() : null; - if (tsa) - { - auto e = new ExpInitializer(loc, tsa.dim); - v = new VarDeclaration(loc, tsa.dim.type, Id.dollar, e, STC.manifest); - } - else - { - auto e = new VoidInitializer(Loc.initial); - e.type = Type.tsize_t; - v = new VarDeclaration(loc, Type.tsize_t, Id.dollar, e); - v.storage_class |= STC.temp | STC.ctfe; // it's never a true static variable - } - } - *pvar = v; - } - (*pvar).dsymbolSemantic(_scope); - return (*pvar); - } - override inout(ArrayScopeSymbol) isArrayScopeSymbol() inout { return this; diff --git a/dmd/dsymbol.h b/dmd/dsymbol.h index 60155761245..f1cadad668f 100644 --- a/dmd/dsymbol.h +++ b/dmd/dsymbol.h @@ -230,7 +230,6 @@ class Dsymbol : public ASTNode virtual Dsymbol *toAlias2(); virtual void setScope(Scope *sc); virtual void importAll(Scope *sc); - virtual Dsymbol *search(const Loc &loc, Identifier *ident, int flags = IgnoreNone); virtual bool overloadInsert(Dsymbol *s); virtual uinteger_t size(const Loc &loc); virtual bool isforwardRef(); @@ -330,16 +329,14 @@ class ScopeDsymbol : public Dsymbol Dsymbols *members; // all Dsymbol's in this scope DsymbolTable *symtab; // members[] sorted into table unsigned endlinnum; // the linnumber of the statement after the scope (0 if unknown) - -private: Dsymbols *importedScopes; // imported Dsymbol's Visibility::Kind *visibilities; // array of `Visibility.Kind`, one for each import +private: BitArray accessiblePackages, privateAccessiblePackages; public: ScopeDsymbol *syntaxCopy(Dsymbol *s) override; - Dsymbol *search(const Loc &loc, Identifier *ident, int flags = SearchLocalsOnly) override; virtual void importScope(Dsymbol *s, Visibility visibility); virtual bool isPackageAccessible(Package *p, Visibility visibility, int flags = 0); bool isforwardRef() override final; @@ -360,7 +357,6 @@ class WithScopeSymbol final : public ScopeDsymbol public: WithStatement *withstate; - Dsymbol *search(const Loc &loc, Identifier *ident, int flags = SearchLocalsOnly) override; WithScopeSymbol *isWithScopeSymbol() override { return this; } void accept(Visitor *v) override { v->visit(this); } @@ -370,10 +366,8 @@ class WithScopeSymbol final : public ScopeDsymbol class ArrayScopeSymbol final : public ScopeDsymbol { -private: - RootObject *arrayContent; public: - Dsymbol *search(const Loc &loc, Identifier *ident, int flags = IgnoreNone) override; + RootObject *arrayContent; ArrayScopeSymbol *isArrayScopeSymbol() override { return this; } void accept(Visitor *v) override { v->visit(this); } @@ -435,3 +429,4 @@ class DsymbolTable final : public RootObject }; void addMember(Dsymbol *dsym, Scope *sc, ScopeDsymbol *sds); +Dsymbol *search(Dsymbol *d, const Loc &loc, Identifier *ident, int flags = SearchLocalsOnly); diff --git a/dmd/dsymbolsem.d b/dmd/dsymbolsem.d index 5441e254a2f..c81a894d20c 100644 --- a/dmd/dsymbolsem.d +++ b/dmd/dsymbolsem.d @@ -7791,3 +7791,617 @@ void checkPrintfScanfSignature(FuncDeclaration funcdecl, TypeFunction f, Scope* p, funcdecl.toChars()); } } + +/********************************************* + * Search for ident as member of d. + * Params: + * d = dsymbol where ident is searched for + * loc = location to print for error messages + * ident = identifier to search for + * flags = IgnoreXXXX + * Returns: + * null if not found + */ +extern(C++) Dsymbol search(Dsymbol d, const ref Loc loc, Identifier ident, int flags = IgnoreNone) +{ + scope v = new SearchVisitor(loc, ident, flags); + d.accept(v); + return v.result; +} + +private extern(C++) class SearchVisitor : Visitor +{ + alias visit = Visitor.visit; + + const Loc loc; + Identifier ident; + int flags; + Dsymbol result; + + this(const ref Loc loc, Identifier ident, int flags) + { + this.loc = loc; + this.ident = ident; + this.flags = flags; + } + + void setResult(Dsymbol d) + { + result = d; + } + + override void visit(Dsymbol d) + { + //printf("Dsymbol::search(this=%p,%s, ident='%s')\n", d, d.toChars(), ident.toChars()); + return setResult(null); + } + + override void visit(ScopeDsymbol sds) + { + //printf("%s.ScopeDsymbol::search(ident='%s', flags=x%x)\n", sds.toChars(), ident.toChars(), flags); + //if (strcmp(ident.toChars(),"c") == 0) *(char*)0=0; + + // Look in symbols declared in this module + if (sds.symtab && !(flags & SearchImportsOnly)) + { + //printf(" look in locals\n"); + auto s1 = sds.symtab.lookup(ident); + if (s1) + { + //printf("\tfound in locals = '%s.%s'\n",toChars(),s1.toChars()); + return setResult(s1); + } + } + //printf(" not found in locals\n"); + + // Look in imported scopes + if (!sds.importedScopes) + return setResult(null); + + //printf(" look in imports\n"); + Dsymbol s = null; + OverloadSet a = null; + // Look in imported modules + for (size_t i = 0; i < sds.importedScopes.length; i++) + { + // If private import, don't search it + if ((flags & IgnorePrivateImports) && sds.visibilities[i] == Visibility.Kind.private_) + continue; + int sflags = flags & (IgnoreErrors | IgnoreAmbiguous); // remember these in recursive searches + Dsymbol ss = (*sds.importedScopes)[i]; + //printf("\tscanning import '%s', visibilities = %d, isModule = %p, isImport = %p\n", ss.toChars(), visibilities[i], ss.isModule(), ss.isImport()); + + if (ss.isModule()) + { + if (flags & SearchLocalsOnly) + continue; + } + else // mixin template + { + if (flags & SearchImportsOnly) + continue; + + sflags |= SearchLocalsOnly; + } + + /* Don't find private members if ss is a module + */ + Dsymbol s2 = ss.search(loc, ident, sflags | (ss.isModule() ? IgnorePrivateImports : IgnoreNone)); + import dmd.access : symbolIsVisible; + if (!s2 || !(flags & IgnoreSymbolVisibility) && !symbolIsVisible(sds, s2)) + continue; + if (!s) + { + s = s2; + if (s && s.isOverloadSet()) + a = sds.mergeOverloadSet(ident, a, s); + } + else if (s2 && s != s2) + { + if (s.toAlias() == s2.toAlias() || s.getType() == s2.getType() && s.getType()) + { + /* After following aliases, we found the same + * symbol, so it's not an ambiguity. But if one + * alias is deprecated or less accessible, prefer + * the other. + */ + if (s.isDeprecated() || s.visible() < s2.visible() && s2.visible().kind != Visibility.Kind.none) + s = s2; + } + else + { + /* Two imports of the same module should be regarded as + * the same. + */ + Import i1 = s.isImport(); + Import i2 = s2.isImport(); + if (!(i1 && i2 && (i1.mod == i2.mod || (!i1.parent.isImport() && !i2.parent.isImport() && i1.ident.equals(i2.ident))))) + { + /* https://issues.dlang.org/show_bug.cgi?id=8668 + * Public selective import adds AliasDeclaration in module. + * To make an overload set, resolve aliases in here and + * get actual overload roots which accessible via s and s2. + */ + s = s.toAlias(); + s2 = s2.toAlias(); + /* If both s2 and s are overloadable (though we only + * need to check s once) + */ + + auto so2 = s2.isOverloadSet(); + if ((so2 || s2.isOverloadable()) && (a || s.isOverloadable())) + { + if (symbolIsVisible(sds, s2)) + { + a = sds.mergeOverloadSet(ident, a, s2); + } + if (!symbolIsVisible(sds, s)) + s = s2; + continue; + } + + /* Two different overflow sets can have the same members + * https://issues.dlang.org/show_bug.cgi?id=16709 + */ + auto so = s.isOverloadSet(); + if (so && so2) + { + if (so.a.length == so2.a.length) + { + foreach (j; 0 .. so.a.length) + { + if (so.a[j] !is so2.a[j]) + goto L1; + } + continue; // the same + L1: + { } // different + } + } + + if (flags & IgnoreAmbiguous) // if return NULL on ambiguity + return setResult(null); + + /* If two imports from C import files, pick first one, as C has global name space + */ + if (s.isCsymbol() && s2.isCsymbol()) + continue; + + if (!(flags & IgnoreErrors)) + ScopeDsymbol.multiplyDefined(loc, s, s2); + break; + } + } + } + } + if (s) + { + /* Build special symbol if we had multiple finds + */ + if (a) + { + if (!s.isOverloadSet()) + a = sds.mergeOverloadSet(ident, a, s); + s = a; + } + //printf("\tfound in imports %s.%s\n", toChars(), s.toChars()); + return setResult(s); + } + //printf(" not found in imports\n"); + return setResult(null); + } + + override void visit(WithScopeSymbol ws) + { + //printf("WithScopeSymbol.search(%s)\n", ident.toChars()); + if (flags & SearchImportsOnly) + return setResult(null); + // Acts as proxy to the with class declaration + Dsymbol s = null; + Expression eold = null; + for (Expression e = ws.withstate.exp; e && e != eold; e = resolveAliasThis(ws._scope, e, true)) + { + if (auto se = e.isScopeExp()) + { + s = se.sds; + } + else if (e.isTypeExp()) + { + s = e.type.toDsymbol(null); + } + else + { + Type t = e.type.toBasetype(); + s = t.toDsymbol(null); + } + if (s) + { + s = s.search(loc, ident, flags); + if (s) + return setResult(s); + } + eold = e; + } + return setResult(null); + } + + override void visit(ArrayScopeSymbol ass) + { + //printf("ArrayScopeSymbol::search('%s', flags = %d)\n", ident.toChars(), flags); + if (ident != Id.dollar) + return setResult(null); + + VarDeclaration* pvar; + Expression ce; + + static Dsymbol dollarFromTypeTuple(const ref Loc loc, TypeTuple tt, Scope* sc) + { + + /* $ gives the number of type entries in the type tuple + */ + auto v = new VarDeclaration(loc, Type.tsize_t, Id.dollar, null); + Expression e = new IntegerExp(Loc.initial, tt.arguments.length, Type.tsize_t); + v._init = new ExpInitializer(Loc.initial, e); + v.storage_class |= STC.temp | STC.static_ | STC.const_; + v.dsymbolSemantic(sc); + return v; + } + + const DYNCAST kind = ass.arrayContent.dyncast(); + switch (kind) with (DYNCAST) + { + case dsymbol: + TupleDeclaration td = cast(TupleDeclaration) ass.arrayContent; + /* $ gives the number of elements in the tuple + */ + auto v = new VarDeclaration(loc, Type.tsize_t, Id.dollar, null); + Expression e = new IntegerExp(Loc.initial, td.objects.length, Type.tsize_t); + v._init = new ExpInitializer(Loc.initial, e); + v.storage_class |= STC.temp | STC.static_ | STC.const_; + v.dsymbolSemantic(ass._scope); + return setResult(v); + case type: + return setResult(dollarFromTypeTuple(loc, cast(TypeTuple) ass.arrayContent, ass._scope)); + default: + break; + } + Expression exp = cast(Expression) ass.arrayContent; + if (auto ie = exp.isIndexExp()) + { + /* array[index] where index is some function of $ + */ + pvar = &ie.lengthVar; + ce = ie.e1; + } + else if (auto se = exp.isSliceExp()) + { + /* array[lwr .. upr] where lwr or upr is some function of $ + */ + pvar = &se.lengthVar; + ce = se.e1; + } + else if (auto ae = exp.isArrayExp()) + { + /* array[e0, e1, e2, e3] where e0, e1, e2 are some function of $ + * $ is a opDollar!(dim)() where dim is the dimension(0,1,2,...) + */ + pvar = &ae.lengthVar; + ce = ae.e1; + } + else + { + /* Didn't find $, look in enclosing scope(s). + */ + return setResult(null); + } + ce = ce.lastComma(); + /* If we are indexing into an array that is really a type + * tuple, rewrite this as an index into a type tuple and + * try again. + */ + if (auto te = ce.isTypeExp()) + { + if (auto ttp = te.type.isTypeTuple()) + return setResult(dollarFromTypeTuple(loc, ttp, ass._scope)); + } + /* *pvar is lazily initialized, so if we refer to $ + * multiple times, it gets set only once. + */ + if (!*pvar) // if not already initialized + { + /* Create variable v and set it to the value of $ + */ + VarDeclaration v; + Type t; + if (auto tupexp = ce.isTupleExp()) + { + /* It is for an expression tuple, so the + * length will be a const. + */ + Expression e = new IntegerExp(Loc.initial, tupexp.exps.length, Type.tsize_t); + v = new VarDeclaration(loc, Type.tsize_t, Id.dollar, new ExpInitializer(Loc.initial, e)); + v.storage_class |= STC.temp | STC.static_ | STC.const_; + } + else if (ce.type && (t = ce.type.toBasetype()) !is null && (t.ty == Tstruct || t.ty == Tclass)) + { + // Look for opDollar + assert(exp.op == EXP.array || exp.op == EXP.slice); + AggregateDeclaration ad = isAggregate(t); + assert(ad); + Dsymbol s = ad.search(loc, Id.opDollar); + if (!s) // no dollar exists -- search in higher scope + return setResult(null); + s = s.toAlias(); + Expression e = null; + // Check for multi-dimensional opDollar(dim) template. + if (TemplateDeclaration td = s.isTemplateDeclaration()) + { + dinteger_t dim = 0; + if (auto ae = exp.isArrayExp()) + { + dim = ae.currentDimension; + } + else if (exp.isSliceExp()) + { + dim = 0; // slices are currently always one-dimensional + } + else + { + assert(0); + } + auto tiargs = new Objects(); + Expression edim = new IntegerExp(Loc.initial, dim, Type.tsize_t); + edim = edim.expressionSemantic(ass._scope); + tiargs.push(edim); + e = new DotTemplateInstanceExp(loc, ce, td.ident, tiargs); + } + else + { + /* opDollar exists, but it's not a template. + * This is acceptable ONLY for single-dimension indexing. + * Note that it's impossible to have both template & function opDollar, + * because both take no arguments. + */ + auto ae = exp.isArrayExp(); + if (ae && ae.arguments.length != 1) + { + error(exp.loc, "`%s` only defines opDollar for one dimension", ad.toChars()); + return setResult(null); + } + Declaration d = s.isDeclaration(); + assert(d); + e = new DotVarExp(loc, ce, d); + } + e = e.expressionSemantic(ass._scope); + if (!e.type) + error(exp.loc, "`%s` has no value", e.toChars()); + t = e.type.toBasetype(); + if (t && t.ty == Tfunction) + e = new CallExp(e.loc, e); + v = new VarDeclaration(loc, null, Id.dollar, new ExpInitializer(Loc.initial, e)); + v.storage_class |= STC.temp | STC.ctfe | STC.rvalue; + } + else + { + /* For arrays, $ will either be a compile-time constant + * (in which case its value in set during constant-folding), + * or a variable (in which case an expression is created in + * toir.c). + */ + + // https://issues.dlang.org/show_bug.cgi?id=16213 + // For static arrays $ is known at compile time, + // so declare it as a manifest constant. + auto tsa = ce.type ? ce.type.isTypeSArray() : null; + if (tsa) + { + auto e = new ExpInitializer(loc, tsa.dim); + v = new VarDeclaration(loc, tsa.dim.type, Id.dollar, e, STC.manifest); + } + else + { + auto e = new VoidInitializer(Loc.initial); + e.type = Type.tsize_t; + v = new VarDeclaration(loc, Type.tsize_t, Id.dollar, e); + v.storage_class |= STC.temp | STC.ctfe; // it's never a true static variable + } + } + *pvar = v; + } + (*pvar).dsymbolSemantic(ass._scope); + return setResult((*pvar)); + + } + + override void visit(Import imp) + { + //printf("%s.Import.search(ident = '%s', flags = x%x)\n", imp.toChars(), ident.toChars(), flags); + if (!imp.pkg) + { + imp.load(null); + imp.mod.importAll(null); + imp.mod.dsymbolSemantic(null); + } + // Forward it to the package/module + return setResult(imp.pkg.search(loc, ident, flags)); + + } + + override void visit(Nspace ns) + { + //printf("%s.Nspace.search('%s')\n", toChars(), ident.toChars()); + if (ns._scope && !ns.symtab) + dsymbolSemantic(ns, ns._scope); + + if (!ns.members || !ns.symtab) // opaque or semantic() is not yet called + { + if (!(flags & IgnoreErrors)) + .error(loc, "%s `%s` is forward referenced when looking for `%s`", ns.kind, ns.toPrettyChars, ident.toChars()); + return setResult(null); + } + + visit(cast(ScopeDsymbol)ns); + } + + override void visit(EnumDeclaration em) + { + //printf("%s.EnumDeclaration::search('%s')\n", em.toChars(), ident.toChars()); + if (em._scope) + { + // Try one last time to resolve this enum + dsymbolSemantic(em, em._scope); + } + + visit(cast(ScopeDsymbol)em); + } + + override void visit(Package pkg) + { + //printf("%s Package.search('%s', flags = x%x)\n", pkg.toChars(), ident.toChars(), flags); + flags &= ~SearchLocalsOnly; // searching an import is always transitive + if (!pkg.isModule() && pkg.mod) + { + // Prefer full package name. + Dsymbol s = pkg.symtab ? pkg.symtab.lookup(ident) : null; + if (s) + return setResult(s); + //printf("[%s] through pkdmod: %s\n", loc.toChars(), toChars()); + return setResult(pkg.mod.search(loc, ident, flags)); + } + + visit(cast(ScopeDsymbol)pkg); + } + + override void visit(Module m) + { + /* Since modules can be circularly referenced, + * need to stop infinite recursive searches. + * This is done with the cache. + */ + //printf("%s Module.search('%s', flags = x%x) insearch = %d\n", m.toChars(), ident.toChars(), flags, m.insearch); + if (m.insearch) + return setResult(null); + + /* Qualified module searches always search their imports, + * even if SearchLocalsOnly + */ + if (!(flags & SearchUnqualifiedModule)) + flags &= ~(SearchUnqualifiedModule | SearchLocalsOnly); + + if (m.searchCacheIdent == ident && m.searchCacheFlags == flags) + { + //printf("%s Module::search('%s', flags = %d) insearch = %d searchCacheSymbol = %s\n", + // toChars(), ident.toChars(), flags, insearch, searchCacheSymbol ? searchCacheSymbol.toChars() : "null"); + return setResult(m.searchCacheSymbol); + } + + uint errors = global.errors; + + m.insearch = true; + visit(cast(ScopeDsymbol)m); + Dsymbol s = result; + m.insearch = false; + + if (errors == global.errors) + { + // https://issues.dlang.org/show_bug.cgi?id=10752 + // Can cache the result only when it does not cause + // access error so the side-effect should be reproduced in later search. + m.searchCacheIdent = ident; + m.searchCacheSymbol = s; + m.searchCacheFlags = flags; + } + return setResult(s); + } + + override void visit(Declaration decl) + { + Dsymbol s = null; + if (decl.type) + { + s = decl.type.toDsymbol(decl._scope); + if (s) + s = s.search(loc, ident, flags); + } + return setResult(s); + } + + override void visit(StructDeclaration sd) + { + //printf("%s.StructDeclaration::search('%s', flags = x%x)\n", sd.toChars(), ident.toChars(), flags); + if (sd._scope && !sd.symtab) + dsymbolSemantic(sd, sd._scope); + + if (!sd.members || !sd.symtab) // opaque or semantic() is not yet called + { + // .stringof is always defined (but may be hidden by some other symbol) + if(ident != Id.stringof && !(flags & IgnoreErrors) && sd.semanticRun < PASS.semanticdone) + .error(loc, "%s `%s` is forward referenced when looking for `%s`", sd.kind, sd.toPrettyChars, ident.toChars()); + return setResult(null); + } + + visit(cast(ScopeDsymbol)sd); + } + + override void visit(ClassDeclaration cd) + { + //printf("%s.ClassDeclaration.search('%s', flags=x%x)\n", cd.toChars(), ident.toChars(), flags); + //if (_scope) printf("%s baseok = %d\n", toChars(), baseok); + if (cd._scope && cd.baseok < Baseok.semanticdone) + { + if (!cd.inuse) + { + // must semantic on base class/interfaces + cd.inuse = true; + dsymbolSemantic(cd, null); + cd.inuse = false; + } + } + + if (!cd.members || !cd.symtab) // opaque or addMember is not yet done + { + // .stringof is always defined (but may be hidden by some other symbol) + if (ident != Id.stringof && !(flags & IgnoreErrors) && cd.semanticRun < PASS.semanticdone) + cd.classError("%s `%s` is forward referenced when looking for `%s`", ident.toChars()); + //*(char*)0=0; + return setResult(null); + } + + visit(cast(ScopeDsymbol)cd); + auto s = result; + + // don't search imports of base classes + if (flags & SearchImportsOnly) + return setResult(s); + + if (s) + return setResult(s); + + // Search bases classes in depth-first, left to right order + foreach (b; (*cd.baseclasses)[]) + { + if (!b.sym) + continue; + + if (!b.sym.symtab) + { + cd.classError("%s `%s` base `%s` is forward referenced", b.sym.ident.toChars()); + continue; + } + + import dmd.access : symbolIsVisible; + + s = b.sym.search(loc, ident, flags); + if (!s) + continue; + else if (s == cd) // happens if s is nested in this and derives from this + s = null; + else if (!(flags & IgnoreSymbolVisibility) && !(s.visible().kind == Visibility.Kind.protected_) && !symbolIsVisible(cd, s)) + s = null; + else + break; + } + + return setResult(s); + } +} diff --git a/dmd/dtoh.d b/dmd/dtoh.d index 7c76da99d1b..9f855743ef9 100644 --- a/dmd/dtoh.d +++ b/dmd/dtoh.d @@ -20,6 +20,7 @@ import dmd.astenums; import dmd.arraytypes; import dmd.attrib; import dmd.dsymbol; +import dmd.dsymbolsem; import dmd.errors; import dmd.globals; import dmd.hdrgen; diff --git a/dmd/enum.h b/dmd/enum.h index c0bd1c68ff4..e17e8cf5b0a 100644 --- a/dmd/enum.h +++ b/dmd/enum.h @@ -50,7 +50,6 @@ class EnumDeclaration final : public ScopeDsymbol bool oneMember(Dsymbol **ps, Identifier *ident) override; Type *getType() override; const char *kind() const override; - Dsymbol *search(const Loc &loc, Identifier *ident, int flags = SearchLocalsOnly) override; bool isDeprecated() const override; // is Dsymbol deprecated? Visibility visible() override; bool isSpecial() const; diff --git a/dmd/frontend.h b/dmd/frontend.h index 9fb712be9aa..ed9d9fa9948 100644 --- a/dmd/frontend.h +++ b/dmd/frontend.h @@ -501,7 +501,6 @@ class Dsymbol : public ASTNode virtual Dsymbol* toAlias2(); virtual void setScope(Scope* sc); virtual void importAll(Scope* sc); - virtual Dsymbol* search(const Loc& loc, Identifier* ident, int32_t flags = 0); virtual bool overloadInsert(Dsymbol* s); virtual uinteger_t size(const Loc& loc); virtual bool isforwardRef(); @@ -619,14 +618,13 @@ class ScopeDsymbol : public Dsymbol Array* members; DsymbolTable* symtab; uint32_t endlinnum; -private: Array* importedScopes; Visibility::Kind* visibilities; +private: BitArray accessiblePackages; BitArray privateAccessiblePackages; public: ScopeDsymbol* syntaxCopy(Dsymbol* s) override; - Dsymbol* search(const Loc& loc, Identifier* ident, int32_t flags = 8) override; virtual void importScope(Dsymbol* s, Visibility visibility); virtual bool isPackageAccessible(Package* p, Visibility visibility, int32_t flags = 0); bool isforwardRef() final override; @@ -3941,7 +3939,6 @@ class Nspace final : public ScopeDsymbol Expression* identExp; Nspace* syntaxCopy(Dsymbol* s) override; void setScope(Scope* sc) override; - Dsymbol* search(const Loc& loc, Identifier* ident, int32_t flags = 8) override; bool hasPointers() override; void setFieldOffset(AggregateDeclaration* ad, FieldState& fieldState, bool isunion) override; const char* kind() const override; @@ -5730,9 +5727,7 @@ class ClassDeclaration : public AggregateDeclaration bool com; bool stack; int32_t cppDtorVtblIndex; -private: bool inuse; -public: ThreeState isabstract; Baseok baseok; ObjcClassDeclaration objc; @@ -5747,7 +5742,6 @@ class ClassDeclaration : public AggregateDeclaration virtual bool isBaseOf(ClassDeclaration* cd, int32_t* poffset); bool isBaseInfoComplete() const; - Dsymbol* search(const Loc& loc, Identifier* ident, int32_t flags = 8) final override; void finalizeSize() final override; bool hasMonitor(); bool isFuncHidden(FuncDeclaration* fd); @@ -5803,7 +5797,6 @@ class Declaration : public Dsymbol _d_dynamicArray< const char > mangleOverride; const char* kind() const override; uinteger_t size(const Loc& loc) final override; - Dsymbol* search(const Loc& loc, Identifier* ident, int32_t flags = 8) final override; bool isStatic() const; LINK resolvedLinkage() const; virtual bool isDelete(); @@ -6136,7 +6129,6 @@ class EnumDeclaration final : public ScopeDsymbol bool oneMember(Dsymbol** ps, Identifier* ident) override; Type* getType() override; const char* kind() const override; - Dsymbol* search(const Loc& loc, Identifier* ident, int32_t flags = 8) override; bool isDeprecated() const override; Visibility visible() override; bool isSpecial() const; @@ -6179,7 +6171,6 @@ class Import final : public Dsymbol void importAll(Scope* sc) override; Dsymbol* toAlias() override; void setScope(Scope* sc) override; - Dsymbol* search(const Loc& loc, Identifier* ident, int32_t flags = 8) override; bool overloadInsert(Dsymbol* s) override; Import* isImport() override; void accept(Visitor* v) override; @@ -6209,7 +6200,6 @@ class Package : public ScopeDsymbol bool equals(const RootObject* const o) const override; Package* isPackage() final override; bool isAncestorPackageOf(const Package* const pkg) const; - Dsymbol* search(const Loc& loc, Identifier* ident, int32_t flags = 8) override; void accept(Visitor* v) override; Module* isPackageMod(); void resolvePKGunknown(); @@ -6252,12 +6242,10 @@ class Module final : public Package public: bool selfImports(); bool rootImports(); -private: Identifier* searchCacheIdent; Dsymbol* searchCacheSymbol; int32_t searchCacheFlags; bool insearch; -public: Module* importedFrom; Array* decldefs; Array aimports; @@ -6280,7 +6268,6 @@ class Module final : public Package void importAll(Scope* prevsc) override; int32_t needModuleInfo(); void checkImportDeprecation(const Loc& loc, Scope* sc); - Dsymbol* search(const Loc& loc, Identifier* ident, int32_t flags = 8) override; bool isPackageAccessible(Package* p, Visibility visibility, int32_t flags = 0) override; Dsymbol* symtabInsert(Dsymbol* s) override; static void runDeferredSemantic(); @@ -6496,7 +6483,6 @@ class StructDeclaration : public AggregateDeclaration public: static StructDeclaration* create(const Loc& loc, Identifier* id, bool inObject); StructDeclaration* syntaxCopy(Dsymbol* s) override; - Dsymbol* search(const Loc& loc, Identifier* ident, int32_t flags = 8) final override; const char* kind() const override; void finalizeSize() final override; bool isPOD(); @@ -6521,16 +6507,14 @@ class WithScopeSymbol final : public ScopeDsymbol { public: WithStatement* withstate; - Dsymbol* search(const Loc& loc, Identifier* ident, int32_t flags = 8) override; WithScopeSymbol* isWithScopeSymbol() override; void accept(Visitor* v) override; }; class ArrayScopeSymbol final : public ScopeDsymbol { - RootObject* arrayContent; public: - Dsymbol* search(const Loc& loc, Identifier* ident, int32_t flags = 0) override; + RootObject* arrayContent; ArrayScopeSymbol* isArrayScopeSymbol() override; void accept(Visitor* v) override; }; @@ -6591,6 +6575,8 @@ extern void dsymbolSemantic(Dsymbol* dsym, Scope* sc); extern void addMember(Dsymbol* dsym, Scope* sc, ScopeDsymbol* sds); +extern Dsymbol* search(Dsymbol* d, const Loc& loc, Identifier* ident, int32_t flags = 0); + extern Expression* isExpression(RootObject* o); extern Dsymbol* isDsymbol(RootObject* o); diff --git a/dmd/import.h b/dmd/import.h index cc760e510e1..aeb3621f1eb 100644 --- a/dmd/import.h +++ b/dmd/import.h @@ -44,7 +44,6 @@ class Import final : public Dsymbol void importAll(Scope *sc) override; Dsymbol *toAlias() override; void setScope(Scope* sc) override; - Dsymbol *search(const Loc &loc, Identifier *ident, int flags = SearchLocalsOnly) override; bool overloadInsert(Dsymbol *s) override; Import *isImport() override { return this; } diff --git a/dmd/importc.d b/dmd/importc.d index 98ac9038a0a..2c7699b45ec 100644 --- a/dmd/importc.d +++ b/dmd/importc.d @@ -20,6 +20,7 @@ import dmd.dcast; import dmd.declaration; import dmd.dscope; import dmd.dsymbol; +import dmd.dsymbolsem; import dmd.errors; import dmd.expression; import dmd.expressionsem; diff --git a/dmd/initsem.d b/dmd/initsem.d index 2d92cb87ec5..76c2d8916b0 100644 --- a/dmd/initsem.d +++ b/dmd/initsem.d @@ -24,6 +24,7 @@ import dmd.dinterpret; import dmd.dscope; import dmd.dstruct; import dmd.dsymbol; +import dmd.dsymbolsem; import dmd.dtemplate; import dmd.errors; import dmd.expression; diff --git a/dmd/lambdacomp.d b/dmd/lambdacomp.d index ec070d8ec0b..d19d435f240 100644 --- a/dmd/lambdacomp.d +++ b/dmd/lambdacomp.d @@ -22,6 +22,7 @@ import dmd.astenums; import dmd.declaration; import dmd.denum; import dmd.dsymbol; +import dmd.dsymbolsem; import dmd.dtemplate; import dmd.expression; import dmd.func; diff --git a/dmd/module.h b/dmd/module.h index 6e8153d485a..92efc1656da 100644 --- a/dmd/module.h +++ b/dmd/module.h @@ -43,7 +43,6 @@ class Package : public ScopeDsymbol bool isAncestorPackageOf(const Package * const pkg) const; - Dsymbol *search(const Loc &loc, Identifier *ident, int flags = SearchLocalsOnly) override; void accept(Visitor *v) override { v->visit(this); } Module *isPackageMod(); @@ -124,7 +123,6 @@ class Module final : public Package Module *parse(); // syntactic parse void importAll(Scope *sc) override; int needModuleInfo(); - Dsymbol *search(const Loc &loc, Identifier *ident, int flags = SearchLocalsOnly) override; bool isPackageAccessible(Package *p, Visibility visibility, int flags = 0) override; Dsymbol *symtabInsert(Dsymbol *s) override; static void runDeferredSemantic(); diff --git a/dmd/nspace.d b/dmd/nspace.d index 08b76db255e..a49e0bf0cc2 100644 --- a/dmd/nspace.d +++ b/dmd/nspace.d @@ -99,22 +99,6 @@ extern (C++) final class Nspace : ScopeDsymbol } } - override Dsymbol search(const ref Loc loc, Identifier ident, int flags = SearchLocalsOnly) - { - //printf("%s.Nspace.search('%s')\n", toChars(), ident.toChars()); - if (_scope && !symtab) - dsymbolSemantic(this, _scope); - - if (!members || !symtab) // opaque or semantic() is not yet called - { - if (!(flags & IgnoreErrors)) - .error(loc, "%s `%s` is forward referenced when looking for `%s`", kind, toPrettyChars, ident.toChars()); - return null; - } - - return ScopeDsymbol.search(loc, ident, flags); - } - override bool hasPointers() { //printf("Nspace::hasPointers() %s\n", toChars()); diff --git a/dmd/nspace.h b/dmd/nspace.h index 500816425ae..7d30402c595 100644 --- a/dmd/nspace.h +++ b/dmd/nspace.h @@ -22,7 +22,6 @@ class Nspace final : public ScopeDsymbol Expression *identExp; Nspace *syntaxCopy(Dsymbol *s) override; void setScope(Scope *sc) override; - Dsymbol *search(const Loc &loc, Identifier *ident, int flags = SearchLocalsOnly) override; bool hasPointers() override; void setFieldOffset(AggregateDeclaration *ad, FieldState& fieldState, bool isunion) override; const char *kind() const override; diff --git a/dmd/opover.d b/dmd/opover.d index b445b7b707b..b7bc9257b3e 100644 --- a/dmd/opover.d +++ b/dmd/opover.d @@ -23,6 +23,7 @@ import dmd.declaration; import dmd.dscope; import dmd.dstruct; import dmd.dsymbol; +import dmd.dsymbolsem; import dmd.dtemplate; import dmd.errors; import dmd.expression; diff --git a/tests/dmd/unit/compilable/searching.d b/tests/dmd/unit/compilable/searching.d index 2efb4f20b37..b8ca3d9efc1 100644 --- a/tests/dmd/unit/compilable/searching.d +++ b/tests/dmd/unit/compilable/searching.d @@ -8,6 +8,7 @@ module compilable.searching; import support : afterEach, beforeEach, compiles; import dmd.dsymbol; +import dmd.dsymbolsem; import dmd.dclass : ClassDeclaration; import dmd.declaration : VarDeclaration; import dmd.dtemplate : TemplateDeclaration; From e4dc2c96a79a9a4cb625d4ed60e693cd63b6d47e Mon Sep 17 00:00:00 2001 From: Walter Bright Date: Fri, 17 Nov 2023 21:51:11 -0800 Subject: [PATCH 055/215] refactor pointerBitmap() --- dmd/traits.d | 53 +++++++++++++++++++++++++++++----------------------- 1 file changed, 30 insertions(+), 23 deletions(-) diff --git a/dmd/traits.d b/dmd/traits.d index 050d6500094..0acadbb4604 100644 --- a/dmd/traits.d +++ b/dmd/traits.d @@ -32,6 +32,7 @@ import dmd.dsymbol; import dmd.dsymbolsem; import dmd.dtemplate; import dmd.errors; +import dmd.errorsink; import dmd.expression; import dmd.expressionsem; import dmd.func; @@ -92,44 +93,50 @@ private Dsymbol getDsymbolWithoutExpCtx(RootObject oarg) } /** - * get an array of size_t values that indicate possible pointer words in memory - * if interpreted as the type given as argument - * Returns: the size of the type in bytes, ulong.max on error + * Fill an array of target size_t values that indicate possible pointer words in memory + * if interpreted as the type given as argument. + * One bit in the array per pointer-sized piece of memory + * Params: + * loc = location for error messages + * t = type to generate pointer bitmap from + * data = array forming the bitmap + * eSink = error message sink + * Returns: + * size of the type `t` in bytes, ulong.max on error */ -ulong getTypePointerBitmap(Loc loc, Type t, Array!(ulong)* data) +ulong getTypePointerBitmap(Loc loc, Type t, ref Array!(ulong) data, ErrorSink eSink) { - ulong sz; auto tc = t.isTypeClass(); - if (tc && !tc.sym.isInterfaceDeclaration()) - sz = tc.sym.AggregateDeclaration.size(loc); - else - sz = t.size(loc); + const ulong sz = (tc && !tc.sym.isInterfaceDeclaration()) + ? tc.sym.AggregateDeclaration.size(loc) + : t.size(loc); if (sz == SIZE_INVALID) return ulong.max; - const sz_size_t = Type.tsize_t.size(loc); + const sz_size_t = Type.tsize_t.size(loc); // size of target's size_t + assert(sz_size_t <= ulong.sizeof); if (sz > sz.max - sz_size_t) { - error(loc, "size overflow for type `%s`", t.toChars()); + eSink.error(loc, "size overflow for type `%s`", t.toChars()); return ulong.max; } - ulong bitsPerWord = sz_size_t * 8; - ulong cntptr = (sz + sz_size_t - 1) / sz_size_t; - ulong cntdata = (cntptr + bitsPerWord - 1) / bitsPerWord; + const ulong bitsPerElement = sz_size_t * 8; // bits used in each array element + const ulong cntptr = (sz + sz_size_t - 1) / sz_size_t; // pointers have same size as sz_size_t + const ulong length = (cntptr + bitsPerElement - 1) / bitsPerElement; // a bit per pointer - data.setDim(cast(size_t)cntdata); + data.setDim(cast(size_t)length); data.zero(); ulong offset; - bool error; + bool error; // sticky error indicator void visit(Type t) { void setpointer(ulong off) { ulong ptroff = off / sz_size_t; - (*data)[cast(size_t)(ptroff / (8 * sz_size_t))] |= 1L << (ptroff % (8 * sz_size_t)); + data[cast(size_t)(ptroff / bitsPerElement)] |= 1L << (ptroff % bitsPerElement); } void visitType(Type t) @@ -282,28 +289,28 @@ ulong getTypePointerBitmap(Loc loc, Type t, Array!(ulong)* data) * * Returns: [T.sizeof, pointerbit0-31/63, pointerbit32/64-63/128, ...] */ -private Expression pointerBitmap(TraitsExp e) +private Expression pointerBitmap(TraitsExp e, ErrorSink eSink) { if (!e.args || e.args.length != 1) { - error(e.loc, "a single type expected for trait pointerBitmap"); + eSink.error(e.loc, "a single type expected for trait pointerBitmap"); return ErrorExp.get(); } Type t = getType((*e.args)[0]); if (!t) { - error(e.loc, "`%s` is not a type", (*e.args)[0].toChars()); + eSink.error(e.loc, "`%s` is not a type", (*e.args)[0].toChars()); return ErrorExp.get(); } Array!(ulong) data; - ulong sz = getTypePointerBitmap(e.loc, t, &data); + const ulong sz = getTypePointerBitmap(e.loc, t, data, eSink); if (sz == ulong.max) return ErrorExp.get(); auto exps = new Expressions(data.length + 1); - (*exps)[0] = new IntegerExp(e.loc, sz, Type.tsize_t); + (*exps)[0] = new IntegerExp(e.loc, sz, Type.tsize_t); // [0] is size in bytes of t foreach (size_t i; 1 .. exps.length) (*exps)[i] = new IntegerExp(e.loc, data[cast(size_t) (i - 1)], Type.tsize_t); @@ -1871,7 +1878,7 @@ Expression semanticTraits(TraitsExp e, Scope* sc) } if (e.ident == Id.getPointerBitmap) { - return pointerBitmap(e); + return pointerBitmap(e, global.errorSink); } if (e.ident == Id.initSymbol) { From 9bf2d28974ee664417492571bec12d0ecf24d17a Mon Sep 17 00:00:00 2001 From: Martin Kinkelin Date: Sun, 19 Nov 2023 03:12:12 +0100 Subject: [PATCH 056/215] Move d_do_test unittest build+run from Makefile to run.d AFAICT, the last piece missing from run.d to fully replace the compiler/test/Makefile. --- tests/dmd/Makefile | 21 +-------- tests/dmd/run.d | 110 ++++++++++++++++++++++++++------------------- 2 files changed, 66 insertions(+), 65 deletions(-) diff --git a/tests/dmd/Makefile b/tests/dmd/Makefile index c08cec65e51..3a972700c52 100644 --- a/tests/dmd/Makefile +++ b/tests/dmd/Makefile @@ -107,22 +107,13 @@ ifeq ($(HOST_DMD),) endif endif -# Required version for -lowmem -LOW_MEM_MIN_VERSION = v2.086.0 VERSION = $(filter v2.%, $(shell $(HOST_DMD) --version 2>/dev/null)) -RUN_FLAGS = -g -i -Itools -version=NoMain ifeq ($(VERSION),) # dmd was not found in $PATH USE_GENERATED=1 endif -# Detect whether the host dmd satisfies MIN_VERSION -ifeq ($(LOW_MEM_MIN_VERSION), $(firstword $(sort $(LOW_MEM_MIN_VERSION) $(VERSION)))) - # dmd found in $PATH is too old - RUN_FLAGS := $(RUN_FLAGS) -lowmem -endif - ifneq ($(USE_GENERATED),) # Use the generated dmd instead of the host compiler HOST_DMD=$(DMD) @@ -218,17 +209,7 @@ start_all_tests: $(RUNNER) @echo "Running all tests" $(EXECUTE_RUNNER) all -$(RESULTS_DIR)/d_do_test$(EXE): tools/d_do_test.d tools/sanitize_json.d $(RESULTS_DIR)/.created - @echo "Building d_do_test tool" - @echo "OS: '$(OS)'" - @echo "MODEL: '$(MODEL)'" - @echo "PIC: '$(PIC_FLAG)'" - $(RUN_HOST_DMD) $(MODEL_FLAG) $(PIC_FLAG) $(RUN_FLAGS) -unittest -run $< - $(RUN_HOST_DMD) $(MODEL_FLAG) $(PIC_FLAG) $(RUN_FLAGS) -od$(RESULTS_DIR) -of$@ $< - -# Build d_do_test here to run it's unittests -# TODO: Migrate this to run.d -$(RUNNER): run.d $(RESULTS_DIR)/d_do_test$(EXE) +$(RUNNER): run.d $(RUN_HOST_DMD) $(MODEL_FLAG) $(PIC_FLAG) -g -od$(RESULTS_DIR) -of$(RUNNER) -i -release $< # run.d is not reentrant because each invocation might attempt to build the required tools diff --git a/tests/dmd/run.d b/tests/dmd/run.d index f2ae5f7c939..79ad1308602 100755 --- a/tests/dmd/run.d +++ b/tests/dmd/run.d @@ -48,24 +48,29 @@ immutable slowRunnableTests = [ enum toolsDir = testPath("tools"); -enum TestTools -{ - unitTestRunner = TestTool("unit_test_runner", [toolsDir.buildPath("paths")]), - testRunner = TestTool("d_do_test", ["-I" ~ toolsDir, "-i", "-version=NoMain"]), - jsonSanitizer = TestTool("sanitize_json"), - dshellPrebuilt = TestTool("dshell_prebuilt", null, Yes.linksWithTests), -} +enum TestTool unitTestRunner = { name: "unit_test_runner", extraArgs: [toolsDir.buildPath("paths")] }; +enum TestTool testRunner = { name: "d_do_test", extraArgs: ["-I" ~ toolsDir, "-i", "-version=NoMain"] }; +enum TestTool testRunnerUnittests = { name: "d_do_test-ut", + customSourceFile: toolsDir.buildPath("d_do_test.d"), + extraArgs: testRunner.extraArgs ~ ["-g", "-unittest"], + runAfterBuild: true }; +enum TestTool jsonSanitizer = { name: "sanitize_json" }; +enum TestTool dshellPrebuilt = { name: "dshell_prebuilt", linksWithTests: true }; immutable struct TestTool { /// The name of the tool. string name; + string customSourceFile; + /// Extra arguments that should be supplied to the compiler when compiling the tool. string[] extraArgs; /// Indicates the tool is a binary that links with tests - Flag!"linksWithTests" linksWithTests; + bool linksWithTests; + + bool runAfterBuild; alias name this; } @@ -144,11 +149,11 @@ Options: if (runUnitTests) { - ensureToolsExists(env, TestTools.unitTestRunner); + ensureToolsExists(env, unitTestRunner); return spawnProcess(unitTestRunnerCommand ~ args, env, Config.none, scriptDir).wait(); } - ensureToolsExists(env, EnumMembers!TestTools); + ensureToolsExists(env, unitTestRunner, testRunner, testRunnerUnittests, jsonSanitizer, dshellPrebuilt); if (args == ["tools"]) return 0; @@ -265,55 +270,70 @@ void ensureToolsExists(const string[string] env, const TestTool[] tools ...) foreach (tool; tools.parallel(1)) { string targetBin; - string sourceFile; + string sourceFile = tool.customSourceFile; if (tool.linksWithTests) { targetBin = resultsDir.buildPath(tool).objName; - sourceFile = toolsDir.buildPath(tool, tool ~ ".d"); + if (sourceFile is null) + sourceFile = toolsDir.buildPath(tool, tool ~ ".d"); } else { targetBin = resultsDir.buildPath(tool).exeName; - sourceFile = toolsDir.buildPath(tool ~ ".d"); + if (sourceFile is null) + sourceFile = toolsDir.buildPath(tool ~ ".d"); } if (targetBin.timeLastModified.ifThrown(SysTime.init) >= sourceFile.timeLastModified) + { log("%s is already up-to-date", tool); + continue; + } + + string[] buildCommand; + bool overrideEnv; + if (tool.linksWithTests) + { + // This will compile the dshell library thus needs the actual + // DMD compiler under test + buildCommand = [ + env["DMD"], + "-conf=", + "-m"~env["MODEL"], + "-of" ~ targetBin, + "-c", + sourceFile + ] ~ getPicFlags(env); + overrideEnv = true; + } else { - string[] command; - bool overrideEnv; - if (tool.linksWithTests) - { - // This will compile the dshell library thus needs the actual - // DMD compiler under test - command = [ - env["DMD"], - "-conf=", - "-m"~env["MODEL"], - "-of" ~ targetBin, - "-c", - sourceFile - ] ~ getPicFlags(env); - overrideEnv = true; - } - else - { - string model = env["MODEL"]; - if (model == "32omf") model = "32"; - - command = [ - hostDMD, - "-m"~model, - "-of"~targetBin, - sourceFile - ] ~ getPicFlags(env) ~ tool.extraArgs; - } + string model = env["MODEL"]; + if (model == "32omf") model = "32"; + + buildCommand = [ + hostDMD, + "-m"~model, + "-of"~targetBin, + sourceFile + ] ~ getPicFlags(env) ~ tool.extraArgs; + } - writefln("Executing: %-(%s %)", command); + writefln("Executing: %-(%s %)", buildCommand); + stdout.flush(); + if (spawnProcess(buildCommand, overrideEnv ? env : null).wait) + { + stderr.writefln("failed to build '%s'", targetBin); + atomicOp!"+="(failCount, 1); + continue; + } + + if (tool.runAfterBuild) + { + writefln("Executing: %s", targetBin); stdout.flush(); - if (spawnProcess(command, overrideEnv ? env : null).wait) + if (spawnProcess([targetBin], null).wait) { - stderr.writefln("failed to build '%s'", targetBin); + stderr.writefln("'%s' failed", targetBin); atomicOp!"+="(failCount, 1); } } @@ -386,7 +406,7 @@ Target[] predefinedTargets(string[] targets) Target target = { filename: filename, args: [ - resultsDir.buildPath(TestTools.testRunner.name.exeName), + resultsDir.buildPath(testRunner.name.exeName), Target.normalizedTestName(filename) ] }; From a8ff9df5fa60946afe6652c2694e5513d70fc81a Mon Sep 17 00:00:00 2001 From: Nick Treleaven Date: Sun, 19 Nov 2023 16:37:42 +0000 Subject: [PATCH 057/215] Fix 'no overloads callable using mutable object' wording The error is wrong, it should include the argument types as well. E.g. `fail_compilation/ctor_attr.d` shows this error even though there is actually a mutable overload `foo(string)`. --- dmd/func.d | 4 ++-- tests/dmd/fail_compilation/ctor_attr.d | 2 +- tests/dmd/fail_compilation/diag8101b.d | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/dmd/func.d b/dmd/func.d index 06b171506f5..351faa471f2 100644 --- a/dmd/func.d +++ b/dmd/func.d @@ -3428,8 +3428,8 @@ FuncDeclaration resolveFuncCall(const ref Loc loc, Scope* sc, Dsymbol s, .error(loc, "none of the overloads of `%s` can construct a %sobject with argument types `(%s)`", fd.toChars(), thisBuf.peekChars(), buf.peekChars()); else - .error(loc, "none of the overloads of `%s` are callable using a %sobject", - fd.toChars(), thisBuf.peekChars()); + .error(loc, "none of the overloads of `%s` are callable using a %sobject with argument types `(%s)`", + fd.toChars(), thisBuf.peekChars(), buf.peekChars()); if (!global.gag || global.params.v.showGaggedErrors) printCandidates(loc, fd, sc.isDeprecated()); diff --git a/tests/dmd/fail_compilation/ctor_attr.d b/tests/dmd/fail_compilation/ctor_attr.d index 6acc300aa38..337ded09fd2 100644 --- a/tests/dmd/fail_compilation/ctor_attr.d +++ b/tests/dmd/fail_compilation/ctor_attr.d @@ -5,7 +5,7 @@ fail_compilation/ctor_attr.d(26): Error: none of the overloads of `this` can con fail_compilation/ctor_attr.d(16): Candidates are: `ctor_attr.S.this(int x) const` fail_compilation/ctor_attr.d(18): `ctor_attr.S.this(string x)` fail_compilation/ctor_attr.d(17): `this()(int x) shared` -fail_compilation/ctor_attr.d(28): Error: none of the overloads of `foo` are callable using a mutable object +fail_compilation/ctor_attr.d(28): Error: none of the overloads of `foo` are callable using a mutable object with argument types `(int)` fail_compilation/ctor_attr.d(20): Candidates are: `ctor_attr.S.foo(int x) immutable` fail_compilation/ctor_attr.d(21): `ctor_attr.S.foo(string x)` --- diff --git a/tests/dmd/fail_compilation/diag8101b.d b/tests/dmd/fail_compilation/diag8101b.d index a55ef731ad2..626fb827878 100644 --- a/tests/dmd/fail_compilation/diag8101b.d +++ b/tests/dmd/fail_compilation/diag8101b.d @@ -6,7 +6,7 @@ fail_compilation/diag8101b.d(19): Candidates are: `diag8101b.S.foo(int __ fail_compilation/diag8101b.d(20): `diag8101b.S.foo(int __param_0, int __param_1)` fail_compilation/diag8101b.d(30): Error: function `diag8101b.S.bar(int __param_0)` is not callable using argument types `(double)` fail_compilation/diag8101b.d(30): cannot pass argument `1.0` of type `double` to parameter `int __param_0` -fail_compilation/diag8101b.d(33): Error: none of the overloads of `foo` are callable using a `const` object +fail_compilation/diag8101b.d(33): Error: none of the overloads of `foo` are callable using a `const` object with argument types `(int)` fail_compilation/diag8101b.d(19): Candidates are: `diag8101b.S.foo(int __param_0)` fail_compilation/diag8101b.d(20): `diag8101b.S.foo(int __param_0, int __param_1)` fail_compilation/diag8101b.d(35): Error: mutable method `diag8101b.S.bar` is not callable using a `const` object From 64aa1bdeb10a1d525f228e2160bb6fbbcdcef008 Mon Sep 17 00:00:00 2001 From: Iain Buclaw Date: Tue, 21 Nov 2023 12:00:22 +0100 Subject: [PATCH 058/215] Fix unittest failure in rt/aaA.d Underlying cause for writing the test this way was fixed in dlang/dmd!15774. Hiding symbols behind `version (unittest)` is problematic because it introduces linker errors when building the unit-tests of other modules. ``` ld: /tmp/ccjp8CS1.o:(.data.rel.ro+0x1c8): undefined reference to `_D4core8internal5newaa3Foo6__initZ' ld: /tmp/ccjp8CS1.o:(.data.rel.ro+0x1d0): undefined reference to `_D4core8internal5newaa3Foo9__xtoHashFNbNeKxSQBqQBoQBiQBfZm' ld: /tmp/ccjp8CS1.o:(.data.rel.ro+0x1d8): undefined reference to `_D4core8internal5newaa3Foo11__xopEqualsMxFKxSQBrQBpQBjQBgZb' ld: /tmp/ccjp8CS1.o:(.data.rel.ro+0x328): undefined reference to `_D4core8internal5newaa__T5EntryTSQBfQBdQx3FooTiZQx6__initZ' ld: /tmp/ccjp8CS1.o:(.data.rel.ro+0x330): undefined reference to `_D4core8internal5newaa__T5EntryTSQBfQBdQx3FooTiZQx9__xtoHashFNbNeKxSQCoQCmQCg__TQCdTQCaTiZQCnZm' ld: /tmp/ccjp8CS1.o:(.data.rel.ro+0x338): undefined reference to `_D4core8internal5newaa__T5EntryTSQBfQBdQx3FooTiZQx11__xopEqualsMxFKxSQCpQCnQCh__TQCeTQCbTiZQCoZb' ``` --- runtime/druntime/src/core/internal/newaa.d | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/runtime/druntime/src/core/internal/newaa.d b/runtime/druntime/src/core/internal/newaa.d index 654791a5dec..2fd93651a22 100644 --- a/runtime/druntime/src/core/internal/newaa.d +++ b/runtime/druntime/src/core/internal/newaa.d @@ -154,13 +154,14 @@ AAShell makeAA(K, V)(V[K] src) @trusted K.sizeof, V.sizeof, E.value.offsetof, flags, hashFn)); } -version(unittest): -struct Foo { - ubyte x; - double d; -} -int[Foo] utaa = [Foo(1, 2.0) : 5]; -unittest { +unittest +{ + static struct Foo + { + ubyte x; + double d; + } + static int[Foo] utaa = [Foo(1, 2.0) : 5]; auto k = Foo(1, 2.0); // verify that getHash doesn't match hashOf for Foo assert(typeid(Foo).getHash(&k) != hashOf(k)); From c5158852d14e29646ef7610020cc03ecb03eea8a Mon Sep 17 00:00:00 2001 From: Walter Bright Date: Tue, 21 Nov 2023 13:45:18 -0800 Subject: [PATCH 059/215] rename common/string.d to common/smallbuffer.d --- dmd/common/README.md | 2 +- dmd/common/file.d | 2 +- dmd/common/{string.d => smallbuffer.d} | 8 ++++---- dmd/escape.d | 2 +- dmd/root/file.d | 2 +- dmd/root/filename.d | 4 ++-- dmd/root/speller.d | 2 +- dmd/root/string.d | 2 +- dmd/vsoptions.d | 2 +- 9 files changed, 13 insertions(+), 13 deletions(-) rename dmd/common/{string.d => smallbuffer.d} (97%) diff --git a/dmd/common/README.md b/dmd/common/README.md index 853fd4ff502..ad507c75bd4 100644 --- a/dmd/common/README.md +++ b/dmd/common/README.md @@ -5,4 +5,4 @@ | [bitfields.d](https://github.com/dlang/dmd/blob/master/compiler/src/dmd/common/bitfields.d) | Pack multiple boolean fields into bit fields | | [file.d](https://github.com/dlang/dmd/blob/master/compiler/src/dmd/common/file.d) | Functions and objects dedicated to file I/O and management | | [outbuffer.d](https://github.com/dlang/dmd/blob/master/compiler/src/dmd/common/outbuffer.d) | An expandable buffer in which you can write text or binary data | -| [string.d](https://github.com/dlang/dmd/blob/master/compiler/src/dmd/common/string.d) | Common string functions including filename manipulation | +| [string.d](https://github.com/dlang/dmd/blob/master/compiler/src/dmd/common/smallbuffer.d) | Common string functions including filename manipulation | diff --git a/dmd/common/file.d b/dmd/common/file.d index 076f357e50b..0fd23892dc6 100644 --- a/dmd/common/file.d +++ b/dmd/common/file.d @@ -23,7 +23,7 @@ import core.sys.windows.winnt; import core.sys.posix.fcntl; import core.sys.posix.unistd; -import dmd.common.string; +import dmd.common.smallbuffer; nothrow: diff --git a/dmd/common/string.d b/dmd/common/smallbuffer.d similarity index 97% rename from dmd/common/string.d rename to dmd/common/smallbuffer.d index 9453a3474da..0dd8e6d1bd1 100644 --- a/dmd/common/string.d +++ b/dmd/common/smallbuffer.d @@ -4,11 +4,11 @@ * Copyright: Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved * Authors: Walter Bright, https://www.digitalmars.com * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) - * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/common/string.d, common/_string.d) - * Documentation: https://dlang.org/phobos/dmd_common_string.html - * Coverage: https://codecov.io/gh/dlang/dmd/src/master/src/dmd/common/string.d + * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/common/smallbuffer.d, common/_smallbuffer.d) + * Documentation: https://dlang.org/phobos/dmd_common_smallbuffer.html + * Coverage: https://codecov.io/gh/dlang/dmd/src/master/src/dmd/common/smallbuffer */ -module dmd.common.string; +module dmd.common.smallbuffer; nothrow: diff --git a/dmd/escape.d b/dmd/escape.d index e25fc84234e..f928b08503a 100644 --- a/dmd/escape.d +++ b/dmd/escape.d @@ -2343,7 +2343,7 @@ void finishScopeParamInference(FuncDeclaration funcdecl, ref TypeFunction f) VarDeclaration[10] tmp = void; size_t dim = (funcdecl.vthis !is null) + (funcdecl.parameters ? funcdecl.parameters.length : 0); - import dmd.common.string : SmallBuffer; + import dmd.common.smallbuffer : SmallBuffer; auto sb = SmallBuffer!VarDeclaration(dim, tmp[]); VarDeclaration[] array = sb[]; diff --git a/dmd/root/file.d b/dmd/root/file.d index 1fb105682ea..fdf13d4e8b0 100644 --- a/dmd/root/file.d +++ b/dmd/root/file.d @@ -24,7 +24,7 @@ import dmd.root.rmem; import dmd.root.string; import dmd.common.file; -import dmd.common.string; +import dmd.common.smallbuffer; nothrow: diff --git a/dmd/root/filename.d b/dmd/root/filename.d index 631c08c44d2..8f31f212048 100644 --- a/dmd/root/filename.d +++ b/dmd/root/filename.d @@ -37,7 +37,7 @@ version (Windows) import core.sys.windows.windef; import core.sys.windows.winnls; - import dmd.common.string : extendedPathThen; + import dmd.common.smallbuffer : extendedPathThen; extern (Windows) DWORD GetFullPathNameW(LPCWSTR, DWORD, LPWSTR, LPWSTR*) nothrow @nogc; extern (Windows) void SetLastError(DWORD) nothrow @nogc; @@ -1177,7 +1177,7 @@ version(Windows) */ private auto toWStringzThen(alias F)(const(char)[] str) nothrow { - import dmd.common.string : SmallBuffer, toWStringz; + import dmd.common.smallbuffer : SmallBuffer, toWStringz; if (!str.length) return F(""w.ptr); diff --git a/dmd/root/speller.d b/dmd/root/speller.d index b646bdda0cc..7ad08b7216e 100644 --- a/dmd/root/speller.d +++ b/dmd/root/speller.d @@ -42,7 +42,7 @@ private: import core.stdc.stdlib; import core.stdc.string; -import dmd.common.string : SmallBuffer; +import dmd.common.smallbuffer : SmallBuffer; enum isSearchFunction(alias fun) = is(searchFunctionType!fun); alias searchFunctionType(alias fun) = typeof(() {int x; return fun("", x);}()); diff --git a/dmd/root/string.d b/dmd/root/string.d index 8b204ab4cad..5ee81a9b63d 100644 --- a/dmd/root/string.d +++ b/dmd/root/string.d @@ -69,7 +69,7 @@ The return value of `T` auto toCStringThen(alias dg)(const(char)[] src) nothrow { import dmd.root.rmem : mem; - import dmd.common.string : SmallBuffer; + import dmd.common.smallbuffer : SmallBuffer; const len = src.length + 1; char[512] small = void; diff --git a/dmd/vsoptions.d b/dmd/vsoptions.d index be8f735c605..82aab48dbc9 100644 --- a/dmd/vsoptions.d +++ b/dmd/vsoptions.d @@ -571,7 +571,7 @@ extern(D): // one with the largest version that also contains the test file static const(char)* findLatestSDKDir(const(char)* baseDir, string testfile) { - import dmd.common.string : SmallBuffer, toWStringz; + import dmd.common.smallbuffer : SmallBuffer, toWStringz; const(char)* pattern = FileName.combine(baseDir, "*"); wchar[1024] support = void; From 17283449d32916bc4e0f6cd60c7168f212c0189f Mon Sep 17 00:00:00 2001 From: Nick Treleaven Date: Wed, 22 Nov 2023 02:58:46 +0000 Subject: [PATCH 060/215] Fix error message when `leftParenthesis` is missing for `is` expression (dlang/dmd!15844) --- dmd/parse.d | 12 ++++++------ tests/dmd/fail_compilation/misc_parser_err_cov1.d | 2 +- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/dmd/parse.d b/dmd/parse.d index f9d174ab14f..b6f30b93f47 100644 --- a/dmd/parse.d +++ b/dmd/parse.d @@ -8428,7 +8428,12 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer AST.TemplateParameters* tpl = null; nextToken(); - if (token.value == TOK.leftParenthesis) + if (token.value != TOK.leftParenthesis) + { + error("expected `(` following `is`, not `%s`", token.toChars()); + goto Lerr; + } + else { nextToken(); if (token.value == TOK.identifier && peekNext() == TOK.leftParenthesis) @@ -8476,11 +8481,6 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer else check(TOK.rightParenthesis); } - else - { - error("`type identifier : specialization` expected following `is`"); - goto Lerr; - } e = new AST.IsExp(loc, targ, ident, tok, tspec, tok2, tpl); break; } diff --git a/tests/dmd/fail_compilation/misc_parser_err_cov1.d b/tests/dmd/fail_compilation/misc_parser_err_cov1.d index 9de436b0119..a170b77b88c 100644 --- a/tests/dmd/fail_compilation/misc_parser_err_cov1.d +++ b/tests/dmd/fail_compilation/misc_parser_err_cov1.d @@ -7,7 +7,7 @@ fail_compilation/misc_parser_err_cov1.d(30): Error: basic type expected, not `)` fail_compilation/misc_parser_err_cov1.d(31): Error: `__traits(identifier, args...)` expected fail_compilation/misc_parser_err_cov1.d(31): Error: semicolon expected following auto declaration, not `o` fail_compilation/misc_parser_err_cov1.d(31): Error: expression expected, not `)` -fail_compilation/misc_parser_err_cov1.d(32): Error: `type identifier : specialization` expected following `is` +fail_compilation/misc_parser_err_cov1.d(32): Error: expected `(` following `is`, not `;` fail_compilation/misc_parser_err_cov1.d(33): Error: semicolon expected following auto declaration, not `auto` fail_compilation/misc_parser_err_cov1.d(33): Error: found `+` when expecting `(` following `mixin` fail_compilation/misc_parser_err_cov1.d(35): Error: `key:value` expected for associative array literal From d8f396445ccb669c1c750c8980ff6a92e1fdaaf0 Mon Sep 17 00:00:00 2001 From: Walter Bright Date: Tue, 21 Nov 2023 21:02:40 -0800 Subject: [PATCH 061/215] simplify toWStringz() (dlang/dmd!15847) --- dmd/common/smallbuffer.d | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/dmd/common/smallbuffer.d b/dmd/common/smallbuffer.d index 0dd8e6d1bd1..d16fa326104 100644 --- a/dmd/common/smallbuffer.d +++ b/dmd/common/smallbuffer.d @@ -133,7 +133,7 @@ unittest `buffer` containing the converted string. The terminating zero is not part of the returned slice, but is guaranteed to follow it. */ -version(Windows) wchar[] toWStringz(const(char)[] narrow, ref SmallBuffer!wchar buffer) nothrow +version(Windows) wchar[] toWStringz(scope const(char)[] narrow, ref SmallBuffer!wchar buffer) nothrow { import core.sys.windows.winnls : MultiByteToWideChar; import dmd.common.file : CodePage; @@ -141,16 +141,17 @@ version(Windows) wchar[] toWStringz(const(char)[] narrow, ref SmallBuffer!wchar if (narrow is null) return null; - const requiredLength = MultiByteToWideChar(CodePage, 0, narrow.ptr, cast(int) narrow.length, buffer.ptr, cast(int) buffer.length); - if (requiredLength < cast(int) buffer.length) + size_t length; + int i; + while (1) { - buffer[requiredLength] = 0; - return buffer[0 .. requiredLength]; + // https://learn.microsoft.com/en-us/windows/win32/api/stringapiset/nf-stringapiset-multibytetowidechar + length = MultiByteToWideChar(CodePage, 0, narrow.ptr, cast(int) narrow.length, buffer.ptr, cast(int) buffer.length); + if (length < buffer.length) + break; + buffer.create(length + 1); + assert(++i == 1); // ensure loop should only execute once or twice } - - buffer.create(requiredLength + 1); - const length = MultiByteToWideChar(CodePage, 0, narrow.ptr, cast(int) narrow.length, buffer.ptr, requiredLength); - assert(length == requiredLength); buffer[length] = 0; return buffer[0 .. length]; } From 38558a4cdb8a42246ed231d8ec562ada6311e877 Mon Sep 17 00:00:00 2001 From: Nicholas Wilson Date: Wed, 22 Nov 2023 14:38:10 +0800 Subject: [PATCH 062/215] Revert "Revert "Move a couple of functions out of dsymbol.d"" (dlang/dmd!15842) --- dmd/dsymbol.d | 91 -------------------------------------------------- dmd/dsymbol.h | 1 - dmd/frontend.h | 3 +- dmd/typesem.d | 58 ++++++++++++++++++++++++++++++++ dmd/typinf.d | 36 ++++++++++++++++++++ dmd/typinf.h | 3 ++ 6 files changed, 99 insertions(+), 93 deletions(-) diff --git a/dmd/dsymbol.d b/dmd/dsymbol.d index a52745fcc0e..35c36fb6de5 100644 --- a/dmd/dsymbol.d +++ b/dmd/dsymbol.d @@ -44,7 +44,6 @@ import dmd.lexer; import dmd.location; import dmd.mtype; import dmd.nspace; -import dmd.opover; import dmd.root.aav; import dmd.root.rmem; import dmd.rootobject; @@ -798,64 +797,6 @@ extern (C++) class Dsymbol : ASTNode return speller!symbol_search_fp(ident.toString()); } - /*************************************** - * Search for identifier id as a member of `this`. - * `id` may be a template instance. - * - * Params: - * loc = location to print the error messages - * sc = the scope where the symbol is located - * id = the id of the symbol - * flags = the search flags which can be `SearchLocalsOnly` or `IgnorePrivateImports` - * - * Returns: - * symbol found, NULL if not - */ - extern (D) final Dsymbol searchX(const ref Loc loc, Scope* sc, RootObject id, int flags) - { - //printf("Dsymbol::searchX(this=%p,%s, ident='%s')\n", this, toChars(), ident.toChars()); - Dsymbol s = toAlias(); - Dsymbol sm; - if (Declaration d = s.isDeclaration()) - { - if (d.inuse) - { - .error(loc, "circular reference to `%s`", d.toPrettyChars()); - return null; - } - } - switch (id.dyncast()) - { - case DYNCAST.identifier: - sm = s.search(loc, cast(Identifier)id, flags); - break; - case DYNCAST.dsymbol: - { - // It's a template instance - //printf("\ttemplate instance id\n"); - Dsymbol st = cast(Dsymbol)id; - TemplateInstance ti = st.isTemplateInstance(); - sm = s.search(loc, ti.name); - if (!sm) - return null; - sm = sm.toAlias(); - TemplateDeclaration td = sm.isTemplateDeclaration(); - if (!td) - return null; // error but handled later - ti.tempdecl = td; - if (!ti.semanticRun) - ti.dsymbolSemantic(sc); - sm = ti.toAlias(); - break; - } - case DYNCAST.type: - case DYNCAST.expression: - default: - assert(0); - } - return sm; - } - bool overloadInsert(Dsymbol s) { //printf("Dsymbol::overloadInsert('%s')\n", s.toChars()); @@ -1468,38 +1409,6 @@ public: return "ScopeDsymbol"; } - /******************************************* - * Look for member of the form: - * const(MemberInfo)[] getMembers(string); - * Returns NULL if not found - */ - final FuncDeclaration findGetMembers() - { - Dsymbol s = search_function(this, Id.getmembers); - FuncDeclaration fdx = s ? s.isFuncDeclaration() : null; - version (none) - { - // Finish - __gshared TypeFunction tfgetmembers; - if (!tfgetmembers) - { - Scope sc; - sc.eSink = global.errorSink; - auto parameters = new Parameters(); - Parameters* p = new Parameter(STC.in_, Type.tchar.constOf().arrayOf(), null, null); - parameters.push(p); - Type tret = null; - TypeFunction tf = new TypeFunction(parameters, tret, VarArg.none, LINK.d); - tfgetmembers = tf.dsymbolSemantic(Loc.initial, &sc).isTypeFunction(); - } - if (fdx) - fdx = fdx.overloadExactMatch(tfgetmembers); - } - if (fdx && fdx.isVirtual()) - fdx = null; - return fdx; - } - /******************************** * Insert Dsymbol in table. * Params: diff --git a/dmd/dsymbol.h b/dmd/dsymbol.h index e0c2046bf90..f1cadad668f 100644 --- a/dmd/dsymbol.h +++ b/dmd/dsymbol.h @@ -342,7 +342,6 @@ class ScopeDsymbol : public Dsymbol bool isforwardRef() override final; static void multiplyDefined(const Loc &loc, Dsymbol *s1, Dsymbol *s2); const char *kind() const override; - FuncDeclaration *findGetMembers(); virtual Dsymbol *symtabInsert(Dsymbol *s); virtual Dsymbol *symtabLookup(Dsymbol *s, Identifier *id); bool hasStaticCtorOrDtor() override; diff --git a/dmd/frontend.h b/dmd/frontend.h index 9f73a4d6d9f..89ffa7f0db7 100644 --- a/dmd/frontend.h +++ b/dmd/frontend.h @@ -630,7 +630,6 @@ class ScopeDsymbol : public Dsymbol bool isforwardRef() final override; static void multiplyDefined(const Loc& loc, Dsymbol* s1, Dsymbol* s2); const char* kind() const override; - FuncDeclaration* findGetMembers(); virtual Dsymbol* symtabInsert(Dsymbol* s); virtual Dsymbol* symtabLookup(Dsymbol* s, Identifier* id); bool hasStaticCtorOrDtor() override; @@ -8216,6 +8215,8 @@ extern bool isSpeculativeType(Type* t); extern bool builtinTypeInfo(Type* t); +extern FuncDeclaration* findGetMembers(ScopeDsymbol* dsym); + class SemanticTimeTransitiveVisitor : public SemanticTimePermissiveVisitor { public: diff --git a/dmd/typesem.d b/dmd/typesem.d index 8795002cd15..2063a954b99 100644 --- a/dmd/typesem.d +++ b/dmd/typesem.d @@ -372,6 +372,64 @@ private void resolveHelper(TypeQualified mt, const ref Loc loc, Scope* sc, Dsymb pt = t.merge(); } +/*************************************** + * Search for identifier id as a member of `this`. + * `id` may be a template instance. + * + * Params: + * loc = location to print the error messages + * sc = the scope where the symbol is located + * id = the id of the symbol + * flags = the search flags which can be `SearchLocalsOnly` or `IgnorePrivateImports` + * + * Returns: + * symbol found, NULL if not + */ +private Dsymbol searchX(Dsymbol dsym, const ref Loc loc, Scope* sc, RootObject id, int flags) +{ + //printf("Dsymbol::searchX(this=%p,%s, ident='%s')\n", this, toChars(), ident.toChars()); + Dsymbol s = dsym.toAlias(); + Dsymbol sm; + if (Declaration d = s.isDeclaration()) + { + if (d.inuse) + { + .error(loc, "circular reference to `%s`", d.toPrettyChars()); + return null; + } + } + switch (id.dyncast()) + { + case DYNCAST.identifier: + sm = s.search(loc, cast(Identifier)id, flags); + break; + case DYNCAST.dsymbol: + { + // It's a template instance + //printf("\ttemplate instance id\n"); + Dsymbol st = cast(Dsymbol)id; + TemplateInstance ti = st.isTemplateInstance(); + sm = s.search(loc, ti.name); + if (!sm) + return null; + sm = sm.toAlias(); + TemplateDeclaration td = sm.isTemplateDeclaration(); + if (!td) + return null; // error but handled later + ti.tempdecl = td; + if (!ti.semanticRun) + ti.dsymbolSemantic(sc); + sm = ti.toAlias(); + break; + } + case DYNCAST.type: + case DYNCAST.expression: + default: + assert(0); + } + return sm; +} + /****************************************** * We've mistakenly parsed `t` as a type. * Redo `t` as an Expression only if there are no type modifiers. diff --git a/dmd/typinf.d b/dmd/typinf.d index 5890fa1b61d..0d0ae35df91 100644 --- a/dmd/typinf.d +++ b/dmd/typinf.d @@ -15,13 +15,17 @@ import dmd.astenums; import dmd.declaration; import dmd.dmodule; import dmd.dscope; +import dmd.dsymbol; import dmd.dclass; import dmd.dstruct; import dmd.errors; import dmd.expression; +import dmd.func; import dmd.globals; +import dmd.id; import dmd.location; import dmd.mtype; +import dmd.opover; import core.stdc.stdio; /**************************************************** @@ -271,3 +275,35 @@ extern (C++) bool builtinTypeInfo(Type t) } return false; } + +/******************************************* + * Look for member of the form: + * const(MemberInfo)[] getMembers(string); + * Returns NULL if not found + */ +extern(C++) FuncDeclaration findGetMembers(ScopeDsymbol dsym) +{ + Dsymbol s = search_function(dsym, Id.getmembers); + FuncDeclaration fdx = s ? s.isFuncDeclaration() : null; + version (none) + { + // Finish + __gshared TypeFunction tfgetmembers; + if (!tfgetmembers) + { + Scope sc; + sc.eSink = global.errorSink; + auto parameters = new Parameters(); + Parameters* p = new Parameter(STC.in_, Type.tchar.constOf().arrayOf(), null, null); + parameters.push(p); + Type tret = null; + TypeFunction tf = new TypeFunction(parameters, tret, VarArg.none, LINK.d); + tfgetmembers = tf.dsymbolSemantic(Loc.initial, &sc).isTypeFunction(); + } + if (fdx) + fdx = fdx.overloadExactMatch(tfgetmembers); + } + if (fdx && fdx.isVirtual()) + fdx = null; + return fdx; +} diff --git a/dmd/typinf.h b/dmd/typinf.h index 76f623a0a3e..b5c144fa8ee 100644 --- a/dmd/typinf.h +++ b/dmd/typinf.h @@ -15,8 +15,11 @@ class Expression; class Type; struct Scope; +class FuncDeclaration; +class ScopeDsymbol; bool genTypeInfo(Expression *e, const Loc &loc, Type *torig, Scope *sc); Type *getTypeInfoType(const Loc &loc, Type *t, Scope *sc, bool genObjCode = true); bool isSpeculativeType(Type *t); bool builtinTypeInfo(Type *t); +FuncDeclaration *findGetMembers(ScopeDsymbol *dsym); From 491a313d680b8a4f837fc79b4ff8412fa0f898d2 Mon Sep 17 00:00:00 2001 From: Walter Bright Date: Tue, 21 Nov 2023 23:02:51 -0800 Subject: [PATCH 063/215] replace common.smallbuffer.asDstring() with inline code (dlang/dmd!15846) --- dmd/common/file.d | 13 +++++++------ dmd/common/smallbuffer.d | 22 ---------------------- 2 files changed, 7 insertions(+), 28 deletions(-) diff --git a/dmd/common/file.d b/dmd/common/file.d index 0fd23892dc6..704110f50bd 100644 --- a/dmd/common/file.d +++ b/dmd/common/file.d @@ -17,7 +17,7 @@ module dmd.common.file; import core.stdc.errno : errno; import core.stdc.stdio : fprintf, remove, rename, stderr; import core.stdc.stdlib : exit; -import core.stdc.string : strerror; +import core.stdc.string : strerror, strlen; import core.sys.windows.winbase; import core.sys.windows.winnt; import core.sys.posix.fcntl; @@ -129,7 +129,8 @@ struct FileMapping(Datum) enum openFlags = CREATE_ALWAYS; } - handle = filename.asDString.extendedPathThen!(p => CreateFileW(p.ptr, createFileMode, 0, null, openFlags, FILE_ATTRIBUTE_NORMAL, null)); + handle = filename[0 .. strlen(filename)]. + extendedPathThen!(p => CreateFileW(p.ptr, createFileMode, 0, null, openFlags, FILE_ATTRIBUTE_NORMAL, null)); if (handle == invalidHandle) { static if (is(Datum == const)) @@ -312,7 +313,7 @@ struct FileMapping(Datum) else version(Windows) { import core.sys.windows.winbase; - if (deleteme.asDString.extendedPathThen!(p => DeleteFileW(p.ptr)) == 0) + if (deleteme[0 .. strlen(deleteme)].extendedPathThen!(p => DeleteFileW(p.ptr)) == 0) { fprintf(stderr, "DeleteFileW error %d\n", GetLastError()); return false; @@ -447,8 +448,8 @@ struct FileMapping(Datum) else version(Windows) { import core.sys.windows.winbase; - auto r = oldname.asDString.extendedPathThen!( - p1 => filename.asDString.extendedPathThen!(p2 => MoveFileExW(p1.ptr, p2.ptr, MOVEFILE_REPLACE_EXISTING)) + auto r = oldname[0 .. strlen(oldname)].extendedPathThen!( + p1 => filename[0 .. strlen(filename)].extendedPathThen!(p2 => MoveFileExW(p1.ptr, p2.ptr, MOVEFILE_REPLACE_EXISTING)) ); if (r == 0) { @@ -483,7 +484,7 @@ extern(D) static bool writeFile(const(char)* name, const void[] data) nothrow else version (Windows) { DWORD numwritten; // here because of the gotos - const nameStr = name.asDString; + const nameStr = name[0 .. strlen(name)]; // work around Windows file path length limitation // (see documentation for extendedPathThen). HANDLE h = nameStr.extendedPathThen! diff --git a/dmd/common/smallbuffer.d b/dmd/common/smallbuffer.d index d16fa326104..ec0eaae647f 100644 --- a/dmd/common/smallbuffer.d +++ b/dmd/common/smallbuffer.d @@ -106,28 +106,6 @@ unittest assert(b[] !is buf[]); } -/** -Converts a zero-terminated C string to a D slice. Takes linear time and allocates no memory. - -Params: -stringz = the C string to be converted - -Returns: -a slice comprehending the string. The terminating 0 is not part of the slice. -*/ -auto asDString(C)(C* stringz) pure @nogc nothrow -{ - import core.stdc.string : strlen; - return stringz[0 .. strlen(stringz)]; -} - -/// -unittest -{ - const char* p = "123".ptr; - assert(p.asDString == "123"); -} - /** (Windows only) Converts a narrow string to a wide string using `buffer` as strorage. Returns a slice managed by `buffer` containing the converted string. The terminating zero is not part of the returned slice, From ae1d2ec6491d44759a40a6b2f03e3b122ecfeb0f Mon Sep 17 00:00:00 2001 From: Walter Bright Date: Wed, 22 Nov 2023 01:41:55 -0800 Subject: [PATCH 064/215] fix Issue 24200 - ImportC: .di file collected macro conflicts with Special Token (dlang/dmd!15797) --- dmd/hdrgen.d | 27 +++++++++++++++++++++++++++ tests/dmd/compilable/ctod.i | 13 +++++++++++++ 2 files changed, 40 insertions(+) diff --git a/dmd/hdrgen.d b/dmd/hdrgen.d index ac2dda3e89f..0944ade4c28 100644 --- a/dmd/hdrgen.d +++ b/dmd/hdrgen.d @@ -1968,6 +1968,10 @@ private void visitVarDecl(VarDeclaration v, bool anywritten, ref OutBuffer buf, v._init.initializerToBuffer(buf, &hgs); } + const commentIt = hgs.importcHdr && isSpecialCName(v.ident); + if (commentIt) + buf.writestring("/+"); + if (anywritten) { buf.writestring(", "); @@ -2000,8 +2004,31 @@ private void visitVarDecl(VarDeclaration v, bool anywritten, ref OutBuffer buf, buf.writestring(" = "); vinit(v); } + if (commentIt) + buf.writestring("+/"); } +/************************************* + * The names __DATE__, __TIME__,__EOF__, __VENDOR__, __TIMESTAMP__, __VERSION__ + * are special to the D lexer and cannot be used as D source variable names. + * Params: + * id = name to check + * Returns: + * true if special C name + */ +private bool isSpecialCName(Identifier id) +{ + auto s = id.toString(); + if (s.length >= 7 && s[0] == '_' && s[1] == '_' && + (id == Id.DATE || + id == Id.TIME || + id == Id.EOFX || + id == Id.VENDOR || + id == Id.TIMESTAMP || + id == Id.VERSIONX)) + return true; + return false; +} /********************************************* * Print expression to buffer. diff --git a/tests/dmd/compilable/ctod.i b/tests/dmd/compilable/ctod.i index 4c77fabadad..090f680a68a 100644 --- a/tests/dmd/compilable/ctod.i +++ b/tests/dmd/compilable/ctod.i @@ -22,6 +22,11 @@ extern (C) int x = void; } Foo abc(); + /+enum int __DATE__ = 1+/; + /+enum int __TIME__ = 1+/; + /+enum int __TIMESTAMP__ = 1+/; + /+enum int __EOF__ = 1+/; + /+enum int __VENDOR__ = 1+/; } --- */ @@ -43,3 +48,11 @@ struct Foo { }; struct Foo abc(void); + +// https://issues.dlang.org/show_bug.cgi?id=24200 + +#define __DATE__ 1 +#define __TIME__ 1 +#define __TIMESTAMP__ 1 +#define __EOF__ 1 +#define __VENDOR__ 1 From bb43a401486c27744d247d2c893bc97df1a4d886 Mon Sep 17 00:00:00 2001 From: Razvan Nitu Date: Wed, 22 Nov 2023 18:10:09 +0200 Subject: [PATCH 065/215] Break dependency of dsymbol.d on dsymbolsem.d (dlang/dmd!15851) --- dmd/dsymbol.d | 65 ------------------------------------------------ dmd/dsymbol.h | 2 +- dmd/dsymbolsem.d | 64 +++++++++++++++++++++++++++++++++++++++++++++++ dmd/frontend.h | 1 - 4 files changed, 65 insertions(+), 67 deletions(-) diff --git a/dmd/dsymbol.d b/dmd/dsymbol.d index 35c36fb6de5..542c4484928 100644 --- a/dmd/dsymbol.d +++ b/dmd/dsymbol.d @@ -31,7 +31,6 @@ import dmd.dmodule; import dmd.dversion; import dmd.dscope; import dmd.dstruct; -import dmd.dsymbolsem; import dmd.dtemplate; import dmd.errors; import dmd.expression; @@ -47,7 +46,6 @@ import dmd.nspace; import dmd.root.aav; import dmd.root.rmem; import dmd.rootobject; -import dmd.root.speller; import dmd.root.string; import dmd.statement; import dmd.staticassert; @@ -385,40 +383,6 @@ extern (C++) class Dsymbol : ASTNode return '`' ~ cstr.toDString() ~ "`\0"; } - final bool checkDeprecated(const ref Loc loc, Scope* sc) - { - if (global.params.useDeprecated == DiagnosticReporting.off) - return false; - if (!this.isDeprecated()) - return false; - // Don't complain if we're inside a deprecated symbol's scope - if (sc.isDeprecated()) - return false; - // Don't complain if we're inside a template constraint - // https://issues.dlang.org/show_bug.cgi?id=21831 - if (sc.flags & SCOPE.constraint) - return false; - - const(char)* message = null; - for (Dsymbol p = this; p; p = p.parent) - { - message = p.depdecl ? p.depdecl.getMessage() : null; - if (message) - break; - } - if (message) - deprecation(loc, "%s `%s` is deprecated - %s", kind, toPrettyChars, message); - else - deprecation(loc, "%s `%s` is deprecated", kind, toPrettyChars); - - if (auto ti = sc.parent ? sc.parent.isInstantiated() : null) - ti.printInstantiationTrace(Classification.deprecation); - else if (auto ti = sc.parent ? sc.parent.isTemplateInstance() : null) - ti.printInstantiationTrace(Classification.deprecation); - - return true; - } - /********************************** * Determine which Module a Dsymbol is in. */ @@ -768,35 +732,6 @@ extern (C++) class Dsymbol : ASTNode { } - extern (D) final Dsymbol search_correct(Identifier ident) - { - /*************************************************** - * Search for symbol with correct spelling. - */ - extern (D) Dsymbol symbol_search_fp(const(char)[] seed, out int cost) - { - /* If not in the lexer's string table, it certainly isn't in the symbol table. - * Doing this first is a lot faster. - */ - if (!seed.length) - return null; - Identifier id = Identifier.lookup(seed); - if (!id) - return null; - cost = 0; // all the same cost - Dsymbol s = this; - Module.clearCache(); - return s.search(Loc.initial, id, IgnoreErrors); - } - - if (global.gag) - return null; // don't do it for speculative compiles; too time consuming - // search for exact name first - if (auto s = this.search(Loc.initial, ident, IgnoreErrors)) - return s; - return speller!symbol_search_fp(ident.toString()); - } - bool overloadInsert(Dsymbol s) { //printf("Dsymbol::overloadInsert('%s')\n", s.toChars()); diff --git a/dmd/dsymbol.h b/dmd/dsymbol.h index f1cadad668f..02973650555 100644 --- a/dmd/dsymbol.h +++ b/dmd/dsymbol.h @@ -205,7 +205,6 @@ class Dsymbol : public ASTNode const char *locToChars(); bool equals(const RootObject * const o) const override; bool isAnonymous() const; - bool checkDeprecated(const Loc &loc, Scope *sc); Module *getModule(); bool isCsymbol(); Module *getAccessModule(); @@ -430,3 +429,4 @@ class DsymbolTable final : public RootObject void addMember(Dsymbol *dsym, Scope *sc, ScopeDsymbol *sds); Dsymbol *search(Dsymbol *d, const Loc &loc, Identifier *ident, int flags = SearchLocalsOnly); +bool checkDeprecated(Dsymbol *d, const Loc &loc, Scope *sc); diff --git a/dmd/dsymbolsem.d b/dmd/dsymbolsem.d index 430377ff874..1e75354caa4 100644 --- a/dmd/dsymbolsem.d +++ b/dmd/dsymbolsem.d @@ -212,6 +212,39 @@ const(char)* getMessage(DeprecatedDeclaration dd) return dd.msgstr; } +bool checkDeprecated(Dsymbol d, const ref Loc loc, Scope* sc) +{ + if (global.params.useDeprecated == DiagnosticReporting.off) + return false; + if (!d.isDeprecated()) + return false; + // Don't complain if we're inside a deprecated symbol's scope + if (sc.isDeprecated()) + return false; + // Don't complain if we're inside a template constraint + // https://issues.dlang.org/show_bug.cgi?id=21831 + if (sc.flags & SCOPE.constraint) + return false; + + const(char)* message = null; + for (Dsymbol p = d; p; p = p.parent) + { + message = p.depdecl ? p.depdecl.getMessage() : null; + if (message) + break; + } + if (message) + deprecation(loc, "%s `%s` is deprecated - %s", d.kind, d.toPrettyChars, message); + else + deprecation(loc, "%s `%s` is deprecated", d.kind, d.toPrettyChars); + + if (auto ti = sc.parent ? sc.parent.isInstantiated() : null) + ti.printInstantiationTrace(Classification.deprecation); + else if (auto ti = sc.parent ? sc.parent.isTemplateInstance() : null) + ti.printInstantiationTrace(Classification.deprecation); + + return true; +} // Returns true if a contract can appear without a function body. package bool allowsContractWithoutBody(FuncDeclaration funcdecl) @@ -7811,6 +7844,37 @@ extern(C++) Dsymbol search(Dsymbol d, const ref Loc loc, Identifier ident, int f return v.result; } +Dsymbol search_correct(Dsymbol d, Identifier ident) +{ + /*************************************************** + * Search for symbol with correct spelling. + */ + Dsymbol symbol_search_fp(const(char)[] seed, out int cost) + { + /* If not in the lexer's string table, it certainly isn't in the symbol table. + * Doing this first is a lot faster. + */ + if (!seed.length) + return null; + Identifier id = Identifier.lookup(seed); + if (!id) + return null; + cost = 0; // all the same cost + Dsymbol s = d; + Module.clearCache(); + return s.search(Loc.initial, id, IgnoreErrors); + } + + if (global.gag) + return null; // don't do it for speculative compiles; too time consuming + // search for exact name first + if (auto s = d.search(Loc.initial, ident, IgnoreErrors)) + return s; + + import dmd.root.speller : speller; + return speller!symbol_search_fp(ident.toString()); +} + private extern(C++) class SearchVisitor : Visitor { alias visit = Visitor.visit; diff --git a/dmd/frontend.h b/dmd/frontend.h index 89ffa7f0db7..da0264babf2 100644 --- a/dmd/frontend.h +++ b/dmd/frontend.h @@ -479,7 +479,6 @@ class Dsymbol : public ASTNode const char* locToChars(); bool equals(const RootObject* const o) const override; bool isAnonymous() const; - bool checkDeprecated(const Loc& loc, Scope* sc); Module* getModule(); bool isCsymbol(); Module* getAccessModule(); From 65f751db16c1e4690a5d16e0da0da667110fa172 Mon Sep 17 00:00:00 2001 From: Walter Bright Date: Wed, 22 Nov 2023 20:10:44 -0800 Subject: [PATCH 066/215] Fix Issue 24125 - ImportC: vector type initializer not understood (dlang/dmd!15838) * fix Issue 24125 - ImportC: vector type initializer not understood * fix Issue 24125 - ImportC: vector type initializer not understood --- dmd/cparse.d | 8 ++++++++ dmd/dcast.d | 12 ++++++++---- dmd/expressionsem.d | 2 +- dmd/initsem.d | 4 ++-- tests/dmd/compilable/test23875.c | 16 ++++++++++++++++ 5 files changed, 35 insertions(+), 7 deletions(-) diff --git a/dmd/cparse.d b/dmd/cparse.d index ed5f1f8b9a2..89a594823ae 100644 --- a/dmd/cparse.d +++ b/dmd/cparse.d @@ -1890,6 +1890,14 @@ final class CParser(AST) : Parser!AST if (specifier.alignExps) error("no alignment-specifier for typedef declaration"); // C11 6.7.5-2 + if (specifier.vector_size) + { + auto length = new AST.IntegerExp(token.loc, specifier.vector_size / dt.size(), AST.Type.tuns32); + auto tsa = new AST.TypeSArray(dt, length); + dt = new AST.TypeVector(tsa); + specifier.vector_size = 0; // used it up + } + bool isalias = true; if (auto ts = dt.isTypeStruct()) { diff --git a/dmd/dcast.d b/dmd/dcast.d index 14c67f062a3..bb86b080be6 100644 --- a/dmd/dcast.d +++ b/dmd/dcast.d @@ -68,7 +68,6 @@ Expression implicitCastTo(Expression e, Scope* sc, Type t) Expression visit(Expression e) { // printf("Expression.implicitCastTo(%s of type %s) => %s\n", e.toChars(), e.type.toChars(), t.toChars()); - if (const match = (sc && sc.flags & SCOPE.Cfile) ? e.cimplicitConvTo(t) : e.implicitConvTo(t)) { // no need for an extra cast when matching is exact @@ -802,8 +801,8 @@ extern(C++) MATCH implicitConvTo(Expression e, Type t) return result; } - else if (tb.ty == Tvector && (typeb.ty == Tarray || typeb.ty == Tsarray)) - { + else if (tb.ty == Tvector && (typeb.ty == Tarray || typeb.ty == Tsarray || typeb.ty == Tpointer)) + { // Tpointer because ImportC eagerly converts Tsarray to Tpointer result = MATCH.exact; // Convert array literal to vector type TypeVector tv = tb.isTypeVector(); @@ -1487,6 +1486,10 @@ MATCH cimplicitConvTo(Expression e, Type t) if (tb.equals(typeb)) return MATCH.exact; + + if (tb.isTypeVector() || typeb.isTypeVector()) + return implicitConvTo(e, t); // permissive checking doesn't apply to vectors + if ((typeb.isintegral() || typeb.isfloating()) && (tb.isintegral() || tb.isfloating())) return MATCH.convert; @@ -2298,9 +2301,10 @@ Expression castTo(Expression e, Scope* sc, Type t, Type att = null) ae.type = tp; } } - else if (tb.ty == Tvector && (typeb.ty == Tarray || typeb.ty == Tsarray)) + else if (tb.ty == Tvector && (typeb.ty == Tarray || typeb.ty == Tsarray || typeb.ty == Tpointer)) { // Convert array literal to vector type + // The Tpointer case comes from C eagerly converting Tsarray to Tpointer TypeVector tv = tb.isTypeVector(); TypeSArray tbase = tv.basetype.isTypeSArray(); assert(tbase.ty == Tsarray); diff --git a/dmd/expressionsem.d b/dmd/expressionsem.d index e6b90183b51..1664bf22dca 100644 --- a/dmd/expressionsem.d +++ b/dmd/expressionsem.d @@ -4387,7 +4387,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor auto e = initializerToExpression(init, t, (sc.flags & SCOPE.Cfile) != 0); if (!e) { - error(cle.loc, "cannot convert initializer `%s` to expression", init.toChars()); + error(cle.loc, "cannot convert initializer `%s` to expression", toChars(init)); return setError(); } result = e; diff --git a/dmd/initsem.d b/dmd/initsem.d index 76c2d8916b0..40623179bb0 100644 --- a/dmd/initsem.d +++ b/dmd/initsem.d @@ -199,7 +199,7 @@ extern(C++) Initializer initializerSemantic(Initializer init, Scope* sc, ref Typ uint length; const(uint) amax = 0x80000000; bool errors = false; - //printf("ArrayInitializer::semantic(%s), ai: %s %p\n", t.toChars(), i.toChars(), i); + //printf("ArrayInitializer::semantic(%s), ai: %s\n", t.toChars(), toChars(i)); if (i.sem) // if semantic() already run { return i; @@ -600,7 +600,7 @@ extern(C++) Initializer initializerSemantic(Initializer init, Scope* sc, ref Typ Initializer visitC(CInitializer ci) { - //printf("CInitializer::semantic() tx: %s t: %s ci: %s\n", (tx ? tx.toChars() : "".ptr), t.toChars(), ci.toChars()); + //printf("CInitializer::semantic() tx: %s t: %s ci: %s\n", (tx ? tx.toChars() : "".ptr), t.toChars(), toChars(ci)); /* Rewrite CInitializer into ExpInitializer, ArrayInitializer, or StructInitializer */ t = t.toBasetype(); diff --git a/tests/dmd/compilable/test23875.c b/tests/dmd/compilable/test23875.c index 6d6f44ec75a..c5ee060cc65 100644 --- a/tests/dmd/compilable/test23875.c +++ b/tests/dmd/compilable/test23875.c @@ -26,3 +26,19 @@ __attribute__((__vector_size__(16))) int pluto(int i) return i ? v1 : v2; } + +// https://issues.dlang.org/show_bug.cgi?id=24125 + +typedef int __i128 __attribute__ ((__vector_size__ (16), __may_alias__)); + +__i128 test1() +{ + return (__i128){ 1, 2, 3, 4 }; +} + +typedef float __m128 __attribute__ ((__vector_size__ (16), __may_alias__)); + +__m128 test2() +{ + return (__m128){ 1, 2, 3, 4 }; +} From 9a78bafe50627cf3cc09832b7c209c6c174e847a Mon Sep 17 00:00:00 2001 From: Walter Bright Date: Fri, 24 Nov 2023 00:41:12 -0800 Subject: [PATCH 067/215] fix Issue 24031 - ImportC: rejects nested C initializers (dlang/dmd!15858) --- dmd/initsem.d | 16 +++++++++- tests/dmd/runnable/test24042.c | 53 ++++++++++++++++++++++++++++++++++ 2 files changed, 68 insertions(+), 1 deletion(-) create mode 100644 tests/dmd/runnable/test24042.c diff --git a/dmd/initsem.d b/dmd/initsem.d index 40623179bb0..6d31f956c8e 100644 --- a/dmd/initsem.d +++ b/dmd/initsem.d @@ -601,6 +601,16 @@ extern(C++) Initializer initializerSemantic(Initializer init, Scope* sc, ref Typ Initializer visitC(CInitializer ci) { //printf("CInitializer::semantic() tx: %s t: %s ci: %s\n", (tx ? tx.toChars() : "".ptr), t.toChars(), toChars(ci)); + static if (0) + if (auto ts = tx.isTypeStruct()) + { + import dmd.common.outbuffer; + OutBuffer buf; + HdrGenStage hgs; + toCBuffer(ts.sym, buf, hgs); + printf("%s\n", buf.peekChars()); + } + /* Rewrite CInitializer into ExpInitializer, ArrayInitializer, or StructInitializer */ t = t.toBasetype(); @@ -794,6 +804,7 @@ extern(C++) Initializer initializerSemantic(Initializer init, Scope* sc, ref Typ for (size_t index = 0; index < ci.initializerList.length; ) { CInitializer cprev; + size_t indexprev; L1: DesigInit di = ci.initializerList[index]; Designators* dlist = di.designatorList; @@ -827,6 +838,7 @@ extern(C++) Initializer initializerSemantic(Initializer init, Scope* sc, ref Typ /* The peeling didn't work, so unpeel it */ ci = cprev; + index = indexprev; di = ci.initializerList[index]; goto L2; } @@ -837,12 +849,14 @@ extern(C++) Initializer initializerSemantic(Initializer init, Scope* sc, ref Typ { if (fieldi == nfields) break; - if (index == 0 && ci.initializerList.length == 1 && di.initializer.isCInitializer()) + if (/*index == 0 && ci.initializerList.length == 1 &&*/ di.initializer.isCInitializer()) { /* Try peeling off this set of { } and see if it works */ cprev = ci; ci = di.initializer.isCInitializer(); + indexprev = index; + index = 0; goto L1; } diff --git a/tests/dmd/runnable/test24042.c b/tests/dmd/runnable/test24042.c new file mode 100644 index 00000000000..529d2397323 --- /dev/null +++ b/tests/dmd/runnable/test24042.c @@ -0,0 +1,53 @@ +// https://issues.dlang.org/show_bug.cgi?id=24031 + +#include + +/**************************************/ + +struct ES { + struct { + char data[24]; + }; + int length; +}; + +struct ES empty = {.data = {1}, .length = 2}; + +void test1() +{ + assert(empty.data[0] == 1); + assert(empty.length == 2); +} + +/**************************************/ + +struct SH { + int k; + struct { + struct { + struct { + int s; + } f; + }; + }; +}; + +struct SH data = (struct SH) { + .k = 1, + {{.f = {.s = 2}}} +}; + +void test2() +{ + assert(data.k == 1); + assert(data.f.s == 2); +} + +/**************************************/ + +int main() +{ + test1(); + test2(); + return 0; +} From 717fa7f46f5211105144ef98f3228d0be710fe8c Mon Sep 17 00:00:00 2001 From: Razvan Nitu Date: Wed, 29 Nov 2023 12:05:11 +0200 Subject: [PATCH 068/215] Move Dsymbol.setScope to dsymbolsem and make it a visitor (dlang/dmd!15866) --- dmd/aggregate.d | 10 ---- dmd/aggregate.h | 1 - dmd/attrib.d | 67 --------------------- dmd/attrib.h | 9 --- dmd/denum.d | 7 --- dmd/dimport.d | 16 ----- dmd/dmodule.d | 2 +- dmd/dsymbol.d | 16 ----- dmd/dsymbol.h | 2 +- dmd/dsymbolsem.d | 150 +++++++++++++++++++++++++++++++++++++++++++++++ dmd/enum.h | 1 - dmd/frontend.h | 16 +---- dmd/import.h | 1 - dmd/nspace.d | 14 ----- dmd/nspace.h | 1 - 15 files changed, 154 insertions(+), 159 deletions(-) diff --git a/dmd/aggregate.d b/dmd/aggregate.d index 307bb0171c4..352ca88f470 100644 --- a/dmd/aggregate.d +++ b/dmd/aggregate.d @@ -178,16 +178,6 @@ extern (C++) abstract class AggregateDeclaration : ScopeDsymbol return sc2; } - override final void setScope(Scope* sc) - { - // Might need a scope to resolve forward references. The check for - // semanticRun prevents unnecessary setting of _scope during deferred - // setScope phases for aggregates which already finished semantic(). - // See https://issues.dlang.org/show_bug.cgi?id=16607 - if (semanticRun < PASS.semanticdone) - ScopeDsymbol.setScope(sc); - } - /*************************************** * Returns: * The total number of fields minus the number of hidden fields. diff --git a/dmd/aggregate.h b/dmd/aggregate.h index cd8f1a15fbd..98fa6bd1bb0 100644 --- a/dmd/aggregate.h +++ b/dmd/aggregate.h @@ -113,7 +113,6 @@ class AggregateDeclaration : public ScopeDsymbol Sizeok sizeok; // set when structsize contains valid data virtual Scope *newScope(Scope *sc); - void setScope(Scope *sc) override final; virtual void finalizeSize() = 0; uinteger_t size(const Loc &loc) override final; bool fill(const Loc &loc, Expressions &elements, bool ctorinit); diff --git a/dmd/attrib.d b/dmd/attrib.d index 251e2e88ca5..faf04890e8e 100644 --- a/dmd/attrib.d +++ b/dmd/attrib.d @@ -123,19 +123,6 @@ extern (C++) abstract class AttribDeclaration : Dsymbol return sc; } - override void setScope(Scope* sc) - { - Dsymbols* d = include(sc); - //printf("\tAttribDeclaration::setScope '%s', d = %p\n",toChars(), d); - if (d) - { - Scope* sc2 = newScope(sc); - d.foreachDsymbol( s => s.setScope(sc2) ); - if (sc2 != sc) - sc2.pop(); - } - } - override void importAll(Scope* sc) { Dsymbols* d = include(sc); @@ -338,14 +325,6 @@ extern (C++) final class DeprecatedDeclaration : StorageClassDeclaration return scx; } - override void setScope(Scope* sc) - { - //printf("DeprecatedDeclaration::setScope() %p\n", this); - if (decl) - Dsymbol.setScope(sc); // for forward reference - return AttribDeclaration.setScope(sc); - } - override void accept(Visitor v) { v.visit(this); @@ -433,13 +412,6 @@ extern (C++) final class CPPMangleDeclaration : AttribDeclaration sc.aligndecl, sc.inlining); } - override void setScope(Scope* sc) - { - if (decl) - Dsymbol.setScope(sc); // for forward reference - return AttribDeclaration.setScope(sc); - } - override const(char)* toChars() const { return toString().ptr; @@ -703,13 +675,6 @@ extern (C++) final class AnonDeclaration : AttribDeclaration return new AnonDeclaration(loc, isunion, Dsymbol.arraySyntaxCopy(decl)); } - override void setScope(Scope* sc) - { - if (decl) - Dsymbol.setScope(sc); - return AttribDeclaration.setScope(sc); - } - override void setFieldOffset(AggregateDeclaration ad, ref FieldState fieldState, bool isunion) { //printf("\tAnonDeclaration::setFieldOffset %s %p\n", isunion ? "union" : "struct", this); @@ -913,11 +878,6 @@ extern (C++) class ConditionalDeclaration : AttribDeclaration } } - override void setScope(Scope* sc) - { - include(sc).foreachDsymbol( s => s.setScope(sc) ); - } - override void accept(Visitor v) { v.visit(this); @@ -983,13 +943,6 @@ extern (C++) final class StaticIfDeclaration : ConditionalDeclaration } } - override void setScope(Scope* sc) - { - // do not evaluate condition before semantic pass - // But do set the scope, in case we need it for forward referencing - Dsymbol.setScope(sc); - } - override void importAll(Scope* sc) { // do not evaluate condition before semantic pass @@ -1104,13 +1057,6 @@ extern (C++) final class StaticForeachDeclaration : AttribDeclaration // change this to give semantics to documentation comments on static foreach declarations } - override void setScope(Scope* sc) - { - // do not evaluate condition before semantic pass - // But do set the scope, in case we need it for forward referencing - Dsymbol.setScope(sc); - } - override void importAll(Scope* sc) { // do not evaluate aggregate before semantic pass @@ -1209,11 +1155,6 @@ extern (C++) final class MixinDeclaration : AttribDeclaration return new MixinDeclaration(loc, Expression.arraySyntaxCopy(exps)); } - override void setScope(Scope* sc) - { - Dsymbol.setScope(sc); - } - override const(char)* kind() const { return "mixin"; @@ -1264,14 +1205,6 @@ extern (C++) final class UserAttributeDeclaration : AttribDeclaration return sc2; } - override void setScope(Scope* sc) - { - //printf("UserAttributeDeclaration::setScope() %p\n", this); - if (decl) - Dsymbol.setScope(sc); // for forward reference of UDAs - return AttribDeclaration.setScope(sc); - } - extern (D) static Expressions* concat(Expressions* udas1, Expressions* udas2) { Expressions* udas; diff --git a/dmd/attrib.h b/dmd/attrib.h index efea9af950c..98c5e521977 100644 --- a/dmd/attrib.h +++ b/dmd/attrib.h @@ -26,7 +26,6 @@ class AttribDeclaration : public Dsymbol virtual Dsymbols *include(Scope *sc); virtual Scope *newScope(Scope *sc); - void setScope(Scope *sc) override; void importAll(Scope *sc) override; void addComment(const utf8_t *comment) override; const char *kind() const override; @@ -61,7 +60,6 @@ class DeprecatedDeclaration final : public StorageClassDeclaration DeprecatedDeclaration *syntaxCopy(Dsymbol *s) override; Scope *newScope(Scope *sc) override; - void setScope(Scope *sc) override; void accept(Visitor *v) override { v->visit(this); } }; @@ -84,7 +82,6 @@ class CPPMangleDeclaration final : public AttribDeclaration CPPMangleDeclaration *syntaxCopy(Dsymbol *s) override; Scope *newScope(Scope *sc) override; - void setScope(Scope *sc) override; const char *toChars() const override; void accept(Visitor *v) override { v->visit(this); } }; @@ -135,7 +132,6 @@ class AnonDeclaration final : public AttribDeclaration unsigned anonalignsize; // size of anonymous struct for alignment purposes AnonDeclaration *syntaxCopy(Dsymbol *s) override; - void setScope(Scope *sc) override; void setFieldOffset(AggregateDeclaration *ad, FieldState& fieldState, bool isunion) override; const char *kind() const override; AnonDeclaration *isAnonDeclaration() override { return this; } @@ -163,7 +159,6 @@ class ConditionalDeclaration : public AttribDeclaration bool oneMember(Dsymbol **ps, Identifier *ident) override final; Dsymbols *include(Scope *sc) override; void addComment(const utf8_t *comment) override final; - void setScope(Scope *sc) override; void accept(Visitor *v) override { v->visit(this); } }; @@ -176,7 +171,6 @@ class StaticIfDeclaration final : public ConditionalDeclaration StaticIfDeclaration *syntaxCopy(Dsymbol *s) override; Dsymbols *include(Scope *sc) override; - void setScope(Scope *sc) override; void importAll(Scope *sc) override; StaticIfDeclaration *isStaticIfDeclaration() override { return this; } const char *kind() const override; @@ -196,7 +190,6 @@ class StaticForeachDeclaration final : public AttribDeclaration bool oneMember(Dsymbol **ps, Identifier *ident) override; Dsymbols *include(Scope *sc) override; void addComment(const utf8_t *comment) override; - void setScope(Scope *sc) override; void importAll(Scope *sc) override; const char *kind() const override; void accept(Visitor *v) override { v->visit(this); } @@ -223,7 +216,6 @@ class MixinDeclaration final : public AttribDeclaration d_bool compiled; MixinDeclaration *syntaxCopy(Dsymbol *s) override; - void setScope(Scope *sc) override; const char *kind() const override; void accept(Visitor *v) override { v->visit(this); } }; @@ -239,7 +231,6 @@ class UserAttributeDeclaration final : public AttribDeclaration UserAttributeDeclaration *syntaxCopy(Dsymbol *s) override; Scope *newScope(Scope *sc) override; - void setScope(Scope *sc) override; Expressions *getAttributes(); const char *kind() const override; void accept(Visitor *v) override { v->visit(this); } diff --git a/dmd/denum.d b/dmd/denum.d index 797f6ee0a2d..5713be1e99e 100644 --- a/dmd/denum.d +++ b/dmd/denum.d @@ -83,13 +83,6 @@ extern (C++) final class EnumDeclaration : ScopeDsymbol return ed; } - override void setScope(Scope* sc) - { - if (semanticRun > PASS.initial) - return; - ScopeDsymbol.setScope(sc); - } - override bool oneMember(Dsymbol* ps, Identifier ident) { if (isAnonymous()) diff --git a/dmd/dimport.d b/dmd/dimport.d index 0132e49cbed..5c01a9f5889 100644 --- a/dmd/dimport.d +++ b/dmd/dimport.d @@ -305,22 +305,6 @@ extern (C++) final class Import : Dsymbol return this; } - override void setScope(Scope* sc) - { - Dsymbol.setScope(sc); - if (aliasdecls.length) - { - if (!mod) - importAll(sc); - - sc = sc.push(mod); - sc.visibility = visibility; - foreach (ad; aliasdecls) - ad.setScope(sc); - sc = sc.pop(); - } - } - override bool overloadInsert(Dsymbol s) { /* Allow multiple imports with the same package base, but disallow diff --git a/dmd/dmodule.d b/dmd/dmodule.d index 5f5de6390fb..5c999ae9b94 100644 --- a/dmd/dmodule.d +++ b/dmd/dmodule.d @@ -969,7 +969,7 @@ extern (C++) final class Module : Package * If this works out well, it can be extended to all modules * before any semantic() on any of them. */ - setScope(sc); // remember module scope for semantic + this.setScope(sc); // remember module scope for semantic for (size_t i = 0; i < members.length; i++) { Dsymbol s = (*members)[i]; diff --git a/dmd/dsymbol.d b/dmd/dsymbol.d index 542c4484928..8f5a292a284 100644 --- a/dmd/dsymbol.d +++ b/dmd/dsymbol.d @@ -712,22 +712,6 @@ extern (C++) class Dsymbol : ASTNode return toAlias(); } - /************************************* - * Set scope for future semantic analysis so we can - * deal better with forward references. - */ - void setScope(Scope* sc) - { - //printf("Dsymbol::setScope() %p %s, %p stc = %llx\n", this, toChars(), sc, sc.stc); - if (!sc.nofree) - sc.setNoFree(); // may need it even after semantic() finishes - _scope = sc; - if (sc.depdecl) - depdecl = sc.depdecl; - if (!userAttribDecl) - userAttribDecl = sc.userAttribDecl; - } - void importAll(Scope* sc) { } diff --git a/dmd/dsymbol.h b/dmd/dsymbol.h index 02973650555..15c997027da 100644 --- a/dmd/dsymbol.h +++ b/dmd/dsymbol.h @@ -227,7 +227,6 @@ class Dsymbol : public ASTNode virtual const char *kind() const; virtual Dsymbol *toAlias(); // resolve real symbol virtual Dsymbol *toAlias2(); - virtual void setScope(Scope *sc); virtual void importAll(Scope *sc); virtual bool overloadInsert(Dsymbol *s); virtual uinteger_t size(const Loc &loc); @@ -430,3 +429,4 @@ class DsymbolTable final : public RootObject void addMember(Dsymbol *dsym, Scope *sc, ScopeDsymbol *sds); Dsymbol *search(Dsymbol *d, const Loc &loc, Identifier *ident, int flags = SearchLocalsOnly); bool checkDeprecated(Dsymbol *d, const Loc &loc, Scope *sc); +void setScope(Dsymbol *d, Scope *sc); diff --git a/dmd/dsymbolsem.d b/dmd/dsymbolsem.d index 1e75354caa4..060abfe1896 100644 --- a/dmd/dsymbolsem.d +++ b/dmd/dsymbolsem.d @@ -8471,3 +8471,153 @@ private extern(C++) class SearchVisitor : Visitor return setResult(s); } } +/************************************* + * Set scope for future semantic analysis so we can + * deal better with forward references. + * + * Params: + * d = dsymbol for which the scope is set + * sc = scope that is used to set the value + */ +extern(C++) void setScope(Dsymbol d, Scope* sc) +{ + scope setScopeVisitor = new SetScopeVisitor(sc); + d.accept(setScopeVisitor); +} + +private extern(C++) class SetScopeVisitor : Visitor +{ + alias visit = typeof(super).visit; + Scope* sc; + + this(Scope* sc) + { + this.sc = sc; + } + + override void visit(Dsymbol d) + { + //printf("Dsymbol::setScope() %p %s, %p stc = %llx\n", d, d.toChars(), sc, sc.stc); + if (!sc.nofree) + sc.setNoFree(); // may need it even after semantic() finishes + d._scope = sc; + if (sc.depdecl) + d.depdecl = sc.depdecl; + if (!d.userAttribDecl) + d.userAttribDecl = sc.userAttribDecl; + } + + override void visit(Import i) + { + visit(cast(Dsymbol)i); + if (i.aliasdecls.length) + { + if (!i.mod) + i.importAll(sc); + + sc = sc.push(i.mod); + sc.visibility = i.visibility; + foreach (ad; i.aliasdecls) + ad.setScope(sc); + sc = sc.pop(); + } + } + + override void visit(Nspace ns) + { + visit(cast(Dsymbol)ns); + if (ns.members) + { + assert(sc); + sc = sc.push(ns); + sc.linkage = LINK.cpp; // namespaces default to C++ linkage + sc.parent = ns; + ns.members.foreachDsymbol(s => s.setScope(sc)); + sc.pop(); + } + } + + override void visit(EnumDeclaration ed) + { + if (ed.semanticRun > PASS.initial) + return; + visit(cast(Dsymbol)ed); + } + + override void visit(AggregateDeclaration ad) + { + // Might need a scope to resolve forward references. The check for + // semanticRun prevents unnecessary setting of _scope during deferred + // setScope phases for aggregates which already finished semantic(). + // See https://issues.dlang.org/show_bug.cgi?id=16607 + if (ad.semanticRun < PASS.semanticdone) + visit(cast(Dsymbol)ad); + } + + override void visit(AttribDeclaration atr) + { + Dsymbols* d = atr.include(sc); + //printf("\tAttribDeclaration::setScope '%s', d = %p\n",toChars(), d); + if (d) + { + Scope* sc2 = atr.newScope(sc); + d.foreachDsymbol( s => s.setScope(sc2) ); + if (sc2 != sc) + sc2.pop(); + } + } + + override void visit(DeprecatedDeclaration dd) + { + //printf("DeprecatedDeclaration::setScope() %p\n", this); + if (dd.decl) + visit(cast(Dsymbol)dd); // for forward reference + visit(cast(AttribDeclaration)dd); + } + + override void visit(CPPMangleDeclaration cppmd) + { + if (cppmd.decl) + visit(cast(Dsymbol)cppmd); // for forward reference + visit(cast(AttribDeclaration)cppmd); + } + + override void visit(AnonDeclaration anond) + { + if (anond.decl) + visit(cast(Dsymbol)anond); // for forward reference + visit(cast(AttribDeclaration)anond); + } + + override void visit(ConditionalDeclaration condd) + { + condd.include(sc).foreachDsymbol( s => s.setScope(sc) ); + } + + override void visit(StaticIfDeclaration sid) + { + // do not evaluate condition before semantic pass + // But do set the scope, in case we need it for forward referencing + visit(cast(Dsymbol)sid); // for forward reference + } + + override void visit(StaticForeachDeclaration sfd) + { + // do not evaluate condition before semantic pass + // But do set the scope, in case we need it for forward referencing + visit(cast(Dsymbol)sfd); // for forward reference + } + + override void visit(MixinDeclaration md) + { + visit(cast(Dsymbol)md); + } + + override void visit(UserAttributeDeclaration uad) + { + //printf("UserAttributeDeclaration::setScope() %p\n", this); + if (uad.decl) + visit(cast(Dsymbol)uad); + visit(cast(AttribDeclaration)uad); + } +} diff --git a/dmd/enum.h b/dmd/enum.h index e17e8cf5b0a..5f91ead9e17 100644 --- a/dmd/enum.h +++ b/dmd/enum.h @@ -46,7 +46,6 @@ class EnumDeclaration final : public ScopeDsymbol bool inuse(bool v); EnumDeclaration *syntaxCopy(Dsymbol *s) override; - void setScope(Scope *sc) override; bool oneMember(Dsymbol **ps, Identifier *ident) override; Type *getType() override; const char *kind() const override; diff --git a/dmd/frontend.h b/dmd/frontend.h index da0264babf2..f8a93db92bb 100644 --- a/dmd/frontend.h +++ b/dmd/frontend.h @@ -498,7 +498,6 @@ class Dsymbol : public ASTNode virtual const char* kind() const; virtual Dsymbol* toAlias(); virtual Dsymbol* toAlias2(); - virtual void setScope(Scope* sc); virtual void importAll(Scope* sc); virtual bool overloadInsert(Dsymbol* s); virtual uinteger_t size(const Loc& loc); @@ -3937,7 +3936,6 @@ class Nspace final : public ScopeDsymbol public: Expression* identExp; Nspace* syntaxCopy(Dsymbol* s) override; - void setScope(Scope* sc) override; bool hasPointers() override; void setFieldOffset(AggregateDeclaration* ad, FieldState& fieldState, bool isunion) override; const char* kind() const override; @@ -5314,7 +5312,6 @@ class AggregateDeclaration : public ScopeDsymbol bool disableNew; Sizeok sizeok; virtual Scope* newScope(Scope* sc); - void setScope(Scope* sc) final override; virtual void finalizeSize() = 0; uinteger_t size(const Loc& loc) final override; bool fill(const Loc& loc, Array& elements, bool ctorinit); @@ -5382,7 +5379,6 @@ class AttribDeclaration : public Dsymbol Array* decl; virtual Array* include(Scope* sc); virtual Scope* newScope(Scope* sc); - void setScope(Scope* sc) override; void importAll(Scope* sc) override; void addComment(const char* comment) override; const char* kind() const override; @@ -5414,7 +5410,6 @@ class DeprecatedDeclaration final : public StorageClassDeclaration const char* msgstr; DeprecatedDeclaration* syntaxCopy(Dsymbol* s) override; Scope* newScope(Scope* sc) override; - void setScope(Scope* sc) override; void accept(Visitor* v) override; }; @@ -5435,7 +5430,6 @@ class CPPMangleDeclaration final : public AttribDeclaration CPPMANGLE cppmangle; CPPMangleDeclaration* syntaxCopy(Dsymbol* s) override; Scope* newScope(Scope* sc) override; - void setScope(Scope* sc) override; const char* toChars() const override; void accept(Visitor* v) override; }; @@ -5483,7 +5477,6 @@ class AnonDeclaration final : public AttribDeclaration uint32_t anonstructsize; uint32_t anonalignsize; AnonDeclaration* syntaxCopy(Dsymbol* s) override; - void setScope(Scope* sc) override; void setFieldOffset(AggregateDeclaration* ad, FieldState& fieldState, bool isunion) override; const char* kind() const override; AnonDeclaration* isAnonDeclaration() override; @@ -5509,7 +5502,6 @@ class ConditionalDeclaration : public AttribDeclaration bool oneMember(Dsymbol** ps, Identifier* ident) final override; Array* include(Scope* sc) override; void addComment(const char* comment) final override; - void setScope(Scope* sc) override; void accept(Visitor* v) override; }; @@ -5523,7 +5515,6 @@ class StaticIfDeclaration final : public ConditionalDeclaration public: StaticIfDeclaration* syntaxCopy(Dsymbol* s) override; Array* include(Scope* sc) override; - void setScope(Scope* sc) override; void importAll(Scope* sc) override; const char* kind() const override; StaticIfDeclaration* isStaticIfDeclaration() override; @@ -5542,7 +5533,6 @@ class StaticForeachDeclaration final : public AttribDeclaration bool oneMember(Dsymbol** ps, Identifier* ident) override; Array* include(Scope* sc) override; void addComment(const char* comment) override; - void setScope(Scope* sc) override; void importAll(Scope* sc) override; const char* kind() const override; void accept(Visitor* v) override; @@ -5565,7 +5555,6 @@ class MixinDeclaration final : public AttribDeclaration ScopeDsymbol* scopesym; bool compiled; MixinDeclaration* syntaxCopy(Dsymbol* s) override; - void setScope(Scope* sc) override; const char* kind() const override; MixinDeclaration* isMixinDeclaration() override; void accept(Visitor* v) override; @@ -5577,7 +5566,6 @@ class UserAttributeDeclaration final : public AttribDeclaration Array* atts; UserAttributeDeclaration* syntaxCopy(Dsymbol* s) override; Scope* newScope(Scope* sc) override; - void setScope(Scope* sc) override; Array* getAttributes(); const char* kind() const override; void accept(Visitor* v) override; @@ -6124,7 +6112,6 @@ class EnumDeclaration final : public ScopeDsymbol uint8_t bitFields; public: EnumDeclaration* syntaxCopy(Dsymbol* s) override; - void setScope(Scope* sc) override; bool oneMember(Dsymbol** ps, Identifier* ident) override; Type* getType() override; const char* kind() const override; @@ -6169,7 +6156,6 @@ class Import final : public Dsymbol Import* syntaxCopy(Dsymbol* s) override; void importAll(Scope* sc) override; Dsymbol* toAlias() override; - void setScope(Scope* sc) override; bool overloadInsert(Dsymbol* s) override; Import* isImport() override; void accept(Visitor* v) override; @@ -6577,6 +6563,8 @@ extern void addMember(Dsymbol* dsym, Scope* sc, ScopeDsymbol* sds); extern Dsymbol* search(Dsymbol* d, const Loc& loc, Identifier* ident, int32_t flags = 0); +extern void setScope(Dsymbol* d, Scope* sc); + extern Expression* isExpression(RootObject* o); extern Dsymbol* isDsymbol(RootObject* o); diff --git a/dmd/import.h b/dmd/import.h index aeb3621f1eb..624cd7406a3 100644 --- a/dmd/import.h +++ b/dmd/import.h @@ -43,7 +43,6 @@ class Import final : public Dsymbol Import *syntaxCopy(Dsymbol *s) override; // copy only syntax trees void importAll(Scope *sc) override; Dsymbol *toAlias() override; - void setScope(Scope* sc) override; bool overloadInsert(Dsymbol *s) override; Import *isImport() override { return this; } diff --git a/dmd/nspace.d b/dmd/nspace.d index a49e0bf0cc2..22c6e63a465 100644 --- a/dmd/nspace.d +++ b/dmd/nspace.d @@ -85,20 +85,6 @@ extern (C++) final class Nspace : ScopeDsymbol return ns; } - override void setScope(Scope* sc) - { - ScopeDsymbol.setScope(sc); - if (members) - { - assert(sc); - sc = sc.push(this); - sc.linkage = LINK.cpp; // namespaces default to C++ linkage - sc.parent = this; - members.foreachDsymbol(s => s.setScope(sc)); - sc.pop(); - } - } - override bool hasPointers() { //printf("Nspace::hasPointers() %s\n", toChars()); diff --git a/dmd/nspace.h b/dmd/nspace.h index 7d30402c595..701cc935eb5 100644 --- a/dmd/nspace.h +++ b/dmd/nspace.h @@ -21,7 +21,6 @@ class Nspace final : public ScopeDsymbol public: Expression *identExp; Nspace *syntaxCopy(Dsymbol *s) override; - void setScope(Scope *sc) override; bool hasPointers() override; void setFieldOffset(AggregateDeclaration *ad, FieldState& fieldState, bool isunion) override; const char *kind() const override; From 21a1b4621a153fbf800dc64dece48500c019cf8a Mon Sep 17 00:00:00 2001 From: RazvanN7 Date: Thu, 30 Nov 2023 14:09:20 +0200 Subject: [PATCH 069/215] Attempt at fixing gdc regression --- dmd/dmodule.d | 34 ++++++++++++++++++++++++++++++++++ dmd/frontend.h | 4 ++-- dmd/module.h | 1 + dmd/typinf.d | 36 ------------------------------------ dmd/typinf.h | 1 - 5 files changed, 37 insertions(+), 39 deletions(-) diff --git a/dmd/dmodule.d b/dmd/dmodule.d index 5c999ae9b94..d096e437cf9 100644 --- a/dmd/dmodule.d +++ b/dmd/dmodule.d @@ -33,6 +33,7 @@ import dmd.errorsink; import dmd.expression; import dmd.expressionsem; import dmd.file_manager; +import dmd.func; import dmd.globals; import dmd.id; import dmd.identifier; @@ -1576,3 +1577,36 @@ private const(char)[] processSource (const(ubyte)[] src, Module mod) return buf; } + +/******************************************* + * Look for member of the form: + * const(MemberInfo)[] getMembers(string); + * Returns NULL if not found + */ +extern(C++) FuncDeclaration findGetMembers(ScopeDsymbol dsym) +{ + import dmd.opover : search_function; + Dsymbol s = search_function(dsym, Id.getmembers); + FuncDeclaration fdx = s ? s.isFuncDeclaration() : null; + version (none) + { + // Finish + __gshared TypeFunction tfgetmembers; + if (!tfgetmembers) + { + Scope sc; + sc.eSink = global.errorSink; + auto parameters = new Parameters(); + Parameters* p = new Parameter(STC.in_, Type.tchar.constOf().arrayOf(), null, null); + parameters.push(p); + Type tret = null; + TypeFunction tf = new TypeFunction(parameters, tret, VarArg.none, LINK.d); + tfgetmembers = tf.dsymbolSemantic(Loc.initial, &sc).isTypeFunction(); + } + if (fdx) + fdx = fdx.overloadExactMatch(tfgetmembers); + } + if (fdx && fdx.isVirtual()) + fdx = null; + return fdx; +} diff --git a/dmd/frontend.h b/dmd/frontend.h index f8a93db92bb..c37554168fd 100644 --- a/dmd/frontend.h +++ b/dmd/frontend.h @@ -6297,6 +6297,8 @@ struct ModuleDeclaration final extern void getLocalClasses(Module* mod, Array& aclasses); +extern FuncDeclaration* findGetMembers(ScopeDsymbol* dsym); + extern void gendocfile(Module* m, const char* const ddoctext_ptr, size_t ddoctext_length, const char* const datetime, ErrorSink* eSink, OutBuffer& outbuf); struct Scope final @@ -8202,8 +8204,6 @@ extern bool isSpeculativeType(Type* t); extern bool builtinTypeInfo(Type* t); -extern FuncDeclaration* findGetMembers(ScopeDsymbol* dsym); - class SemanticTimeTransitiveVisitor : public SemanticTimePermissiveVisitor { public: diff --git a/dmd/module.h b/dmd/module.h index 92efc1656da..cab0b0a4c1b 100644 --- a/dmd/module.h +++ b/dmd/module.h @@ -169,3 +169,4 @@ struct ModuleDeclaration }; extern void getLocalClasses(Module* mod, Array& aclasses); +FuncDeclaration *findGetMembers(ScopeDsymbol *dsym); diff --git a/dmd/typinf.d b/dmd/typinf.d index 0d0ae35df91..5890fa1b61d 100644 --- a/dmd/typinf.d +++ b/dmd/typinf.d @@ -15,17 +15,13 @@ import dmd.astenums; import dmd.declaration; import dmd.dmodule; import dmd.dscope; -import dmd.dsymbol; import dmd.dclass; import dmd.dstruct; import dmd.errors; import dmd.expression; -import dmd.func; import dmd.globals; -import dmd.id; import dmd.location; import dmd.mtype; -import dmd.opover; import core.stdc.stdio; /**************************************************** @@ -275,35 +271,3 @@ extern (C++) bool builtinTypeInfo(Type t) } return false; } - -/******************************************* - * Look for member of the form: - * const(MemberInfo)[] getMembers(string); - * Returns NULL if not found - */ -extern(C++) FuncDeclaration findGetMembers(ScopeDsymbol dsym) -{ - Dsymbol s = search_function(dsym, Id.getmembers); - FuncDeclaration fdx = s ? s.isFuncDeclaration() : null; - version (none) - { - // Finish - __gshared TypeFunction tfgetmembers; - if (!tfgetmembers) - { - Scope sc; - sc.eSink = global.errorSink; - auto parameters = new Parameters(); - Parameters* p = new Parameter(STC.in_, Type.tchar.constOf().arrayOf(), null, null); - parameters.push(p); - Type tret = null; - TypeFunction tf = new TypeFunction(parameters, tret, VarArg.none, LINK.d); - tfgetmembers = tf.dsymbolSemantic(Loc.initial, &sc).isTypeFunction(); - } - if (fdx) - fdx = fdx.overloadExactMatch(tfgetmembers); - } - if (fdx && fdx.isVirtual()) - fdx = null; - return fdx; -} diff --git a/dmd/typinf.h b/dmd/typinf.h index b5c144fa8ee..2df2abb6a98 100644 --- a/dmd/typinf.h +++ b/dmd/typinf.h @@ -22,4 +22,3 @@ bool genTypeInfo(Expression *e, const Loc &loc, Type *torig, Scope *sc); Type *getTypeInfoType(const Loc &loc, Type *t, Scope *sc, bool genObjCode = true); bool isSpeculativeType(Type *t); bool builtinTypeInfo(Type *t); -FuncDeclaration *findGetMembers(ScopeDsymbol *dsym); From 876fc1292b2e61c4f8effb9f5ef4df54a8317787 Mon Sep 17 00:00:00 2001 From: RazvanN7 Date: Thu, 30 Nov 2023 14:15:17 +0200 Subject: [PATCH 070/215] Attempt at fixing gdc regression - part 2 --- dmd/canthrow.d | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dmd/canthrow.d b/dmd/canthrow.d index 67305922df6..5a608a9986d 100644 --- a/dmd/canthrow.d +++ b/dmd/canthrow.d @@ -22,7 +22,6 @@ import dmd.declaration; import dmd.dsymbol; import dmd.errorsink; import dmd.expression; -import dmd.expressionsem; import dmd.func; import dmd.globals; import dmd.init; @@ -81,6 +80,7 @@ CT canThrow(Expression e, FuncDeclaration func, ErrorSink eSink) if (!f.isDtorDeclaration()) errorSupplementalInferredAttr(f, 10, false, STC.nothrow_); + import dmd.expressionsem : checkOverriddenDtor; f.checkOverriddenDtor(null, e.loc, dd => dd.type.toTypeFunction().isnothrow, "not nothrow"); } else if (func) From d3c54637b6b9f9af9fdffcf2ef6a7d28e9206a74 Mon Sep 17 00:00:00 2001 From: Denis Feklushkin Date: Mon, 4 Dec 2023 17:24:07 +0700 Subject: [PATCH 071/215] druntime/test/*.mak: replaces -Isrc by -Iimport (dlang/dmd!15881) * druntime/test/*.mak: Replace -Isrc by -Iimport * Fix Windows tests build: rt/tlsgc.d is not in import/ dir --------- Co-authored-by: Denis Feklushkin --- runtime/druntime/test/allocations/win64.mak | 2 +- runtime/druntime/test/betterc/win64.mak | 20 ++++++++++---------- runtime/druntime/test/cpuid/win64.mak | 2 +- runtime/druntime/test/exceptions/win64.mak | 2 +- runtime/druntime/test/gc/win64.mak | 2 +- runtime/druntime/test/init_fini/win64.mak | 2 +- runtime/druntime/test/shared/win64.mak | 12 ++++++------ runtime/druntime/test/stdcpp/win64.mak | 8 ++++---- runtime/druntime/test/uuid/win64.mak | 2 +- 9 files changed, 26 insertions(+), 26 deletions(-) diff --git a/runtime/druntime/test/allocations/win64.mak b/runtime/druntime/test/allocations/win64.mak index 617fb9ee6a3..97dd5267abe 100644 --- a/runtime/druntime/test/allocations/win64.mak +++ b/runtime/druntime/test/allocations/win64.mak @@ -7,6 +7,6 @@ DRUNTIMELIB=druntime64.lib test: alloc_from_assert alloc_from_assert: - $(DMD) -m$(MODEL) -conf= -Isrc -defaultlib=$(DRUNTIMELIB) test\allocations\src\$@.d + $(DMD) -m$(MODEL) -conf= -Iimport -defaultlib=$(DRUNTIMELIB) test\allocations\src\$@.d $@.exe del $@.* diff --git a/runtime/druntime/test/betterc/win64.mak b/runtime/druntime/test/betterc/win64.mak index eb78f088ff1..0e060b54800 100644 --- a/runtime/druntime/test/betterc/win64.mak +++ b/runtime/druntime/test/betterc/win64.mak @@ -8,43 +8,43 @@ TESTS=test18828 test19416 test19421 test19561 test20088 test20613 test19924 test test: $(TESTS) test18828: - $(DMD) -m$(MODEL) -conf= -Isrc -betterC -run test\betterc\src\$@.d + $(DMD) -m$(MODEL) -conf= -Iimport -betterC -run test\betterc\src\$@.d del $@.* test19416: - $(DMD) -m$(MODEL) -conf= -Isrc -betterC -run test\betterc\src\$@.d + $(DMD) -m$(MODEL) -conf= -Iimport -betterC -run test\betterc\src\$@.d del $@.* test19421: - $(DMD) -m$(MODEL) -conf= -Isrc -betterC -run test\betterc\src\$@.d + $(DMD) -m$(MODEL) -conf= -Iimport -betterC -run test\betterc\src\$@.d del $@.* test19561: - $(DMD) -m$(MODEL) -conf= -Isrc -betterC -run test\betterc\src\$@.d + $(DMD) -m$(MODEL) -conf= -Iimport -betterC -run test\betterc\src\$@.d del $@.* test20088: - $(DMD) -m$(MODEL) -conf= -Isrc -betterC -run test\betterc\src\$@.d + $(DMD) -m$(MODEL) -conf= -Iimport -betterC -run test\betterc\src\$@.d del $@.* test20613: - $(DMD) -m$(MODEL) -conf= -Isrc -betterC -run test\betterc\src\$@.d + $(DMD) -m$(MODEL) -conf= -Iimport -betterC -run test\betterc\src\$@.d del $@.* test19924: - $(DMD) -m$(MODEL) -conf= -Isrc -betterC -run test\betterc\src\$@.d + $(DMD) -m$(MODEL) -conf= -Iimport -betterC -run test\betterc\src\$@.d del $@.* test22336: - $(DMD) -m$(MODEL) -conf= -Isrc -betterC -run test\betterc\src\$@.d + $(DMD) -m$(MODEL) -conf= -Iimport -betterC -run test\betterc\src\$@.d del $@.* test19933: - $(DMD) -m$(MODEL) -conf= -Isrc -betterC -run test\betterc\src\$@.d + $(DMD) -m$(MODEL) -conf= -Iimport -betterC -run test\betterc\src\$@.d del $@.* test19933_mingw: # DFLAGS=-mscrtlib=msvcrt120 takes precedence over any command line flags, so # specify vcruntime140.lib explicitly for using mingw with Universal CRT - $(DMD) -m$(MODEL) -conf= -Isrc -betterC -Lvcruntime140.lib -Llegacy_stdio_definitions.lib -L/NODEFAULTLIB:msvcrt120.lib -run test\betterc\src\test19933.d + $(DMD) -m$(MODEL) -conf= -Iimport -betterC -Lvcruntime140.lib -Llegacy_stdio_definitions.lib -L/NODEFAULTLIB:msvcrt120.lib -run test\betterc\src\test19933.d del $@.* diff --git a/runtime/druntime/test/cpuid/win64.mak b/runtime/druntime/test/cpuid/win64.mak index a64c8d7ecfa..37796f1e1d1 100644 --- a/runtime/druntime/test/cpuid/win64.mak +++ b/runtime/druntime/test/cpuid/win64.mak @@ -7,6 +7,6 @@ DRUNTIMELIB=druntime64.lib test: cpuid cpuid: - $(DMD) -g -m$(MODEL) -conf= -Isrc -defaultlib=$(DRUNTIMELIB) test\cpuid\src\cpuid.d + $(DMD) -g -m$(MODEL) -conf= -Iimport -defaultlib=$(DRUNTIMELIB) test\cpuid\src\cpuid.d cpuid.exe del cpuid.exe cpuid.obj diff --git a/runtime/druntime/test/exceptions/win64.mak b/runtime/druntime/test/exceptions/win64.mak index ea4d19e599c..621a718ccc6 100644 --- a/runtime/druntime/test/exceptions/win64.mak +++ b/runtime/druntime/test/exceptions/win64.mak @@ -5,6 +5,6 @@ MODEL=64 DRUNTIMELIB=druntime64.lib test: - $(DMD) -m$(MODEL) -conf= -Isrc -defaultlib=$(DRUNTIMELIB) -g test\exceptions\src\winstack.d + $(DMD) -m$(MODEL) -conf= -Iimport -defaultlib=$(DRUNTIMELIB) -g test\exceptions\src\winstack.d winstack.exe del winstack.* diff --git a/runtime/druntime/test/gc/win64.mak b/runtime/druntime/test/gc/win64.mak index e29092e37d2..8db7bec80c2 100644 --- a/runtime/druntime/test/gc/win64.mak +++ b/runtime/druntime/test/gc/win64.mak @@ -6,7 +6,7 @@ DRUNTIMELIB=druntime64.lib SRC_GC = src/core/internal/gc/impl/conservative/gc.d SRC = $(SRC_GC) src/rt/lifetime.d src/object.d -_DFLAGS = -m$(MODEL) -g -conf= -Isrc -defaultlib=$(DRUNTIMELIB) +_DFLAGS = -m$(MODEL) -g -conf= -Iimport -Isrc -defaultlib=$(DRUNTIMELIB) UDFLAGS = $(_DFLAGS) -unittest -version=CoreUnittest RM = del diff --git a/runtime/druntime/test/init_fini/win64.mak b/runtime/druntime/test/init_fini/win64.mak index b020fec9f66..1a829b675d3 100644 --- a/runtime/druntime/test/init_fini/win64.mak +++ b/runtime/druntime/test/init_fini/win64.mak @@ -7,6 +7,6 @@ DRUNTIMELIB=druntime64.lib test: custom_gc custom_gc: - $(DMD) -m$(MODEL) -conf= -Isrc -defaultlib=$(DRUNTIMELIB) test\init_fini\src\custom_gc.d + $(DMD) -m$(MODEL) -conf= -Iimport -defaultlib=$(DRUNTIMELIB) test\init_fini\src\custom_gc.d custom_gc.exe del custom_gc.exe custom_gc.obj diff --git a/runtime/druntime/test/shared/win64.mak b/runtime/druntime/test/shared/win64.mak index 9658562dffd..878ea636929 100644 --- a/runtime/druntime/test/shared/win64.mak +++ b/runtime/druntime/test/shared/win64.mak @@ -7,24 +7,24 @@ DRUNTIMELIB=druntime64.lib test: loadlibwin dllrefcount dllgc dynamiccast dllrefcount: - $(DMD) -g -m$(MODEL) -conf= -Isrc -defaultlib=$(DRUNTIMELIB) test\shared\src\dllrefcount.d + $(DMD) -g -m$(MODEL) -conf= -Iimport -defaultlib=$(DRUNTIMELIB) test\shared\src\dllrefcount.d dllrefcount.exe del dllrefcount.exe dllrefcount.obj loadlibwin: - $(DMD) -g -m$(MODEL) -conf= -Isrc -defaultlib=$(DRUNTIMELIB) test\shared\src\loadlibwin.d + $(DMD) -g -m$(MODEL) -conf= -Iimport -defaultlib=$(DRUNTIMELIB) test\shared\src\loadlibwin.d loadlibwin.exe del loadlibwin.exe loadlibwin.obj dllgc: - $(DMD) -g -m$(MODEL) -conf= -Isrc -defaultlib=$(DRUNTIMELIB) -version=DLL -shared -ofdllgc.dll test\shared\src\dllgc.d - $(DMD) -g -m$(MODEL) -conf= -Isrc -defaultlib=$(DRUNTIMELIB) -ofloaddllgc.exe test\shared\src\dllgc.d + $(DMD) -g -m$(MODEL) -conf= -Iimport -defaultlib=$(DRUNTIMELIB) -version=DLL -shared -ofdllgc.dll test\shared\src\dllgc.d + $(DMD) -g -m$(MODEL) -conf= -Iimport -defaultlib=$(DRUNTIMELIB) -ofloaddllgc.exe test\shared\src\dllgc.d loaddllgc.exe del loaddllgc.exe loaddllgc.obj dllgc.dll dllgc.obj dynamiccast: - $(DMD) -g -m$(MODEL) -conf= -Isrc -defaultlib=$(DRUNTIMELIB) -version=DLL -shared -ofdynamiccast.dll test\shared\src\dynamiccast.d - $(DMD) -g -m$(MODEL) -conf= -Isrc -defaultlib=$(DRUNTIMELIB) -ofdynamiccast.exe test\shared\src\dynamiccast.d + $(DMD) -g -m$(MODEL) -conf= -Iimport -defaultlib=$(DRUNTIMELIB) -version=DLL -shared -ofdynamiccast.dll test\shared\src\dynamiccast.d + $(DMD) -g -m$(MODEL) -conf= -Iimport -defaultlib=$(DRUNTIMELIB) -ofdynamiccast.exe test\shared\src\dynamiccast.d dynamiccast.exe cmd /c "if not exist dynamiccast_endbar exit 1" cmd /c "if not exist dynamiccast_endmain exit 1" diff --git a/runtime/druntime/test/stdcpp/win64.mak b/runtime/druntime/test/stdcpp/win64.mak index c84651f11ff..04acee2e17a 100644 --- a/runtime/druntime/test/stdcpp/win64.mak +++ b/runtime/druntime/test/stdcpp/win64.mak @@ -18,21 +18,21 @@ test: $(TESTS) $(TESTS): "$(CC)" -c /Fo$@_cpp.obj test\stdcpp\src\$@.cpp /EHsc /MT $(ADD_CFLAGS) - "$(DMD)" -of=$@.exe -m$(MODEL) -conf= -Isrc -defaultlib=$(DRUNTIMELIB) -main -unittest -version=CoreUnittest -version=_MSC_VER_$(_MSC_VER) -mscrtlib=libcmt $(ADD_DFLAGS) test\stdcpp\src\$@_test.d $@_cpp.obj + "$(DMD)" -of=$@.exe -m$(MODEL) -conf= -Iimport -defaultlib=$(DRUNTIMELIB) -main -unittest -version=CoreUnittest -version=_MSC_VER_$(_MSC_VER) -mscrtlib=libcmt $(ADD_DFLAGS) test\stdcpp\src\$@_test.d $@_cpp.obj $@.exe del $@.exe $@.obj $@_cpp.obj "$(CC)" -c /Fo$@_cpp.obj test\stdcpp\src\$@.cpp /EHsc /MD $(ADD_CFLAGS) - "$(DMD)" -of=$@.exe -m$(MODEL) -conf= -Isrc -defaultlib=$(DRUNTIMELIB) -main -unittest -version=CoreUnittest -version=_MSC_VER_$(_MSC_VER) -mscrtlib=msvcrt $(ADD_DFLAGS) test\stdcpp\src\$@_test.d $@_cpp.obj + "$(DMD)" -of=$@.exe -m$(MODEL) -conf= -Iimport -defaultlib=$(DRUNTIMELIB) -main -unittest -version=CoreUnittest -version=_MSC_VER_$(_MSC_VER) -mscrtlib=msvcrt $(ADD_DFLAGS) test\stdcpp\src\$@_test.d $@_cpp.obj $@.exe del $@.exe $@.obj $@_cpp.obj "$(CC)" -c /Fo$@_cpp.obj test\stdcpp\src\$@.cpp /EHsc /MTd $(ADD_CFLAGS) - "$(DMD)" -of=$@.exe -m$(MODEL) -conf= -Isrc -defaultlib=$(DRUNTIMELIB) -main -unittest -version=CoreUnittest -version=_MSC_VER_$(_MSC_VER) -mscrtlib=libcmtd $(ADD_DFLAGS) test\stdcpp\src\$@_test.d $@_cpp.obj + "$(DMD)" -of=$@.exe -m$(MODEL) -conf= -Iimport -defaultlib=$(DRUNTIMELIB) -main -unittest -version=CoreUnittest -version=_MSC_VER_$(_MSC_VER) -mscrtlib=libcmtd $(ADD_DFLAGS) test\stdcpp\src\$@_test.d $@_cpp.obj $@.exe del $@.exe $@.obj $@_cpp.obj "$(CC)" -c /Fo$@_cpp.obj test\stdcpp\src\$@.cpp /EHsc /MDd $(ADD_CFLAGS) - "$(DMD)" -of=$@.exe -m$(MODEL) -conf= -Isrc -defaultlib=$(DRUNTIMELIB) -main -unittest -version=CoreUnittest -version=_MSC_VER_$(_MSC_VER) -mscrtlib=msvcrtd $(ADD_DFLAGS) test\stdcpp\src\$@_test.d $@_cpp.obj + "$(DMD)" -of=$@.exe -m$(MODEL) -conf= -Iimport -defaultlib=$(DRUNTIMELIB) -main -unittest -version=CoreUnittest -version=_MSC_VER_$(_MSC_VER) -mscrtlib=msvcrtd $(ADD_DFLAGS) test\stdcpp\src\$@_test.d $@_cpp.obj $@.exe del $@.exe $@.obj $@_cpp.obj diff --git a/runtime/druntime/test/uuid/win64.mak b/runtime/druntime/test/uuid/win64.mak index 19396926293..ddf9c0c8485 100644 --- a/runtime/druntime/test/uuid/win64.mak +++ b/runtime/druntime/test/uuid/win64.mak @@ -5,5 +5,5 @@ MODEL=64 DRUNTIMELIB=druntime64.lib test: - $(DMD) -m$(MODEL) -conf= -Isrc -defaultlib=$(DRUNTIMELIB) test\uuid\test.d uuid.lib + $(DMD) -m$(MODEL) -conf= -Iimport -defaultlib=$(DRUNTIMELIB) test\uuid\test.d uuid.lib del test.exe test.obj From ff04424ce151facc91064f18fa1dce9ff2eec7a6 Mon Sep 17 00:00:00 2001 From: Denis Feklushkin Date: Mon, 4 Dec 2023 17:53:32 +0700 Subject: [PATCH 072/215] druntime: copydir target removed (dlang/dmd!15879) Co-authored-by: Denis Feklushkin --- runtime/druntime/win32.mak | 5 +---- runtime/druntime/win64.mak | 5 +---- 2 files changed, 2 insertions(+), 8 deletions(-) diff --git a/runtime/druntime/win32.mak b/runtime/druntime/win32.mak index 75d7d5e10b0..5e9ffa66e2d 100644 --- a/runtime/druntime/win32.mak +++ b/runtime/druntime/win32.mak @@ -32,7 +32,7 @@ DRUNTIME=lib\$(DRUNTIME_BASE).lib DOCFMT= -target: copydir copy $(DRUNTIME) +target: copy $(DRUNTIME) $(mak\COPY) $(mak\DOCS) @@ -50,9 +50,6 @@ OBJS_TO_DELETE= errno_c_32omf.obj import: copy -copydir: - "$(MAKE)" -f mak/WINDOWS copydir DMD="$(DMD)" HOST_DMD="$(HOST_DMD)" MODEL=32 IMPDIR="$(IMPDIR)" - copy: "$(MAKE)" -f mak/WINDOWS copy DMD="$(DMD)" HOST_DMD="$(HOST_DMD)" MODEL=32 IMPDIR="$(IMPDIR)" diff --git a/runtime/druntime/win64.mak b/runtime/druntime/win64.mak index be7a3cae83f..8d69bf3e710 100644 --- a/runtime/druntime/win64.mak +++ b/runtime/druntime/win64.mak @@ -37,7 +37,7 @@ DRUNTIME=lib\$(DRUNTIME_BASE).lib DOCFMT= -target: copydir copy $(DRUNTIME) +target: copy $(DRUNTIME) $(mak\COPY) $(mak\DOCS) @@ -53,9 +53,6 @@ OBJS_TO_DELETE= errno_c_$(MODEL).obj import: copy -copydir: - "$(MAKE)" -f mak/WINDOWS copydir DMD="$(DMD)" HOST_DMD="$(HOST_DMD)" MODEL=$(MODEL) IMPDIR="$(IMPDIR)" - copy: "$(MAKE)" -f mak/WINDOWS copy DMD="$(DMD)" HOST_DMD="$(HOST_DMD)" MODEL=$(MODEL) IMPDIR="$(IMPDIR)" From 2fbd436538b13df61c80c92edc0ed80bf18aee80 Mon Sep 17 00:00:00 2001 From: Nick Treleaven Date: Mon, 4 Dec 2023 14:23:55 +0000 Subject: [PATCH 073/215] [object] Document `setSameMutex` (dlang/dmd!15882) --- runtime/druntime/src/object.d | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/runtime/druntime/src/object.d b/runtime/druntime/src/object.d index 5589c0a884f..1b39a27c102 100644 --- a/runtime/druntime/src/object.d +++ b/runtime/druntime/src/object.d @@ -526,6 +526,12 @@ unittest private extern(C) void _d_setSameMutex(shared Object ownee, shared Object owner) nothrow; +/** Makes ownee use owner's mutex. + * This will initialize owner's mutex if it hasn't been set yet. + * Params: + * ownee = object to change + * owner = source object + */ void setSameMutex(shared Object ownee, shared Object owner) { import core.atomic : atomicLoad; From 9cc5a7f94fba415e68868caee068c658b7d38b2b Mon Sep 17 00:00:00 2001 From: Denis Feklushkin Date: Mon, 4 Dec 2023 16:42:53 +0300 Subject: [PATCH 074/215] druntime win64.mak: Unused DDOCFLAGS variable removed --- runtime/druntime/win64.mak | 1 - 1 file changed, 1 deletion(-) diff --git a/runtime/druntime/win64.mak b/runtime/druntime/win64.mak index 8d69bf3e710..ea4f76b02e7 100644 --- a/runtime/druntime/win64.mak +++ b/runtime/druntime/win64.mak @@ -28,7 +28,6 @@ HOST_DMD=dmd DFLAGS=-m$(MODEL) -conf= -O -release -preview=dip1000 -preview=fieldwise -preview=dtorfields -inline -w -Isrc -Iimport UDFLAGS=-m$(MODEL) -conf= -O -release -preview=dip1000 -preview=fieldwise -w -version=_MSC_VER_$(_MSC_VER) -Isrc -Iimport -DDOCFLAGS=-conf= -c -w -o- -Isrc -Iimport -version=CoreDdoc UTFLAGS=-version=CoreUnittest -unittest -checkaction=context From 60acff9c2a101a5d7fb3d766077d99a880b82c46 Mon Sep 17 00:00:00 2001 From: Walter Bright Date: Mon, 4 Dec 2023 22:12:13 -0800 Subject: [PATCH 075/215] fix Issue 23714 - compilable/testcstuff1.c:213:1: error: static assertion failed: u'ab' == 0x610062 (dlang/dmd!15878) --- dmd/lexer.d | 23 ++++++++--------------- tests/dmd/compilable/testcstuff1.c | 2 +- 2 files changed, 9 insertions(+), 16 deletions(-) diff --git a/dmd/lexer.d b/dmd/lexer.d index b8faec76d60..2f541430ac7 100644 --- a/dmd/lexer.d +++ b/dmd/lexer.d @@ -2008,22 +2008,15 @@ class Lexer case 'u': dchar d1; size_t idx; - auto msg = utf_decodeChar(str, idx, d1); - dchar d2 = 0; - if (idx < n && !msg) - msg = utf_decodeChar(str, idx, d2); - if (msg) - error(loc, "%.*s", cast(int)msg.length, msg.ptr); - else if (idx < n) - error(loc, "max number of chars in 16 bit character literal is 2, had %d", - cast(int)((n + 1) >> 1)); - else if (d1 > 0x1_0000) - error(loc, "%d does not fit in 16 bits", d1); - else if (d2 > 0x1_0000) - error(loc, "%d does not fit in 16 bits", d2); + while (idx < n) + { + string msg = utf_decodeChar(str, idx, d1); + if (msg) + error(loc, "%.*s", cast(int)msg.length, msg.ptr); + } + if (d1 >= 0x1_0000) + error(loc, "x%x does not fit in 16 bits", d1); u = d1; - if (d2) - u = (d1 << 16) | d2; break; case 'U': diff --git a/tests/dmd/compilable/testcstuff1.c b/tests/dmd/compilable/testcstuff1.c index 15a907ffcb2..6d6028d0f84 100644 --- a/tests/dmd/compilable/testcstuff1.c +++ b/tests/dmd/compilable/testcstuff1.c @@ -217,7 +217,7 @@ _Static_assert('ab' == 0x6162, "ok"); _Static_assert('abc' == 0x616263, "ok"); _Static_assert('abcd' == 0x61626364, "ok"); _Static_assert(u'a' == 0x61, "ok"); -_Static_assert(u'ab' == 0x610062, "ok"); +_Static_assert(u'ab' == 0x62, "ok"); _Static_assert(U'a' == 0x61, "ok"); _Static_assert(u'\u1234' == 0x1234, "ok"); _Static_assert(L'\u1234' == 0x1234, "ok"); From 8b34d60a39670c25911273eac220e12d66d366c3 Mon Sep 17 00:00:00 2001 From: Walter Bright Date: Mon, 4 Dec 2023 22:16:07 -0800 Subject: [PATCH 076/215] ImportC: support #define IDENT ( expression ) (dlang/dmd!15871) --- dmd/cparse.d | 94 ++++++++++++++++++-------- dmd/errorsink.d | 14 ++++ dmd/lexer.d | 2 +- tests/dmd/compilable/imports/defines.c | 4 ++ tests/dmd/compilable/testdefines.d | 3 + 5 files changed, 88 insertions(+), 29 deletions(-) diff --git a/dmd/cparse.d b/dmd/cparse.d index 89a594823ae..3a39cedc4c2 100644 --- a/dmd/cparse.d +++ b/dmd/cparse.d @@ -4272,6 +4272,7 @@ final class CParser(AST) : Parser!AST case TOK.rightParenthesis: case TOK.rightBracket: case TOK.endOfFile: + case TOK.endOfLine: if (!any) return false; break; @@ -5794,6 +5795,9 @@ final class CParser(AST) : Parser!AST buf.writeByte(0); auto slice = buf.peekChars()[0 .. length]; resetDefineLines(slice); // reset lexer + auto save = eSink; + auto eLatch = new ErrorSinkLatch(); + eSink = eLatch; const(char)* endp = &slice[length - 7]; @@ -5801,40 +5805,40 @@ final class CParser(AST) : Parser!AST // indexed by Identifier, returns index into symbols[] // The memory for this is leaked - void addVar(AST.VarDeclaration v) + void addVar(AST.Dsymbol s) { - //printf("addVar() %s\n", v.toChars()); - v.isCmacro(true); // mark it as coming from a C #define + //printf("addVar() %s\n", s.toChars()); + if (auto v = s.isVarDeclaration()) + v.isCmacro(true); // mark it as coming from a C #define /* If it's already defined, replace the earlier * definition */ - if (size_t* pd = cast(void*)v.ident in defineTab) + if (size_t* pd = cast(void*)s.ident in defineTab) { //printf("replacing %s\n", v.toChars()); - (*symbols)[*pd] = v; + (*symbols)[*pd] = s; return; } - defineTab[cast(void*)v.ident] = symbols.length; - symbols.push(v); + defineTab[cast(void*)s.ident] = symbols.length; + symbols.push(s); } - Token n; - while (p < endp) { if (p[0 .. 7] == "#define") { p += 7; - scan(&n); - //printf("%s\n", n.toChars()); - if (n.value == TOK.identifier) + nextToken(); + //printf("define %s\n", token.toChars()); + if (token.value == TOK.identifier) { - auto id = n.ident; - scan(&n); + auto id = token.ident; + const params = *p == '('; + nextToken(); AST.Type t; - switch (n.value) + switch (token.value) { case TOK.endOfLine: // #define identifier nextDefineLine(); @@ -5847,9 +5851,9 @@ final class CParser(AST) : Parser!AST case TOK.uns64Literal: t = AST.Type.tuns64; goto Linteger; Linteger: - const intvalue = n.intvalue; - scan(&n); - if (n.value == TOK.endOfLine) + const intvalue = token.intvalue; + nextToken(); + if (token.value == TOK.endOfLine) { /* Declare manifest constant: * enum id = intvalue; @@ -5870,9 +5874,9 @@ final class CParser(AST) : Parser!AST case TOK.imaginary80Literal: t = AST.Type.timaginary80; goto Lfloat; Lfloat: - const floatvalue = n.floatvalue; - scan(&n); - if (n.value == TOK.endOfLine) + const floatvalue = token.floatvalue; + nextToken(); + if (token.value == TOK.endOfLine) { /* Declare manifest constant: * enum id = floatvalue; @@ -5886,11 +5890,11 @@ final class CParser(AST) : Parser!AST break; case TOK.string_: - const str = n.ustring; - const len = n.len; - const postfix = n.postfix; - scan(&n); - if (n.value == TOK.endOfLine) + const str = token.ustring; + const len = token.len; + const postfix = token.postfix; + nextToken(); + if (token.value == TOK.endOfLine) { /* Declare manifest constant: * enum id = "string"; @@ -5903,6 +5907,39 @@ final class CParser(AST) : Parser!AST } break; + case TOK.leftParenthesis: + /* Look for: + * #define ID ( expression ) + * and rewrite it to a template function: + * auto ID()() { return expression; } + */ + if (params) + break; // no parameters + nextToken(); + eLatch.sawErrors = false; + auto exp = cparseExpression(); + if (eLatch.sawErrors) // parsing errors + break; // abandon this #define + if (token.value != TOK.rightParenthesis) + break; + nextToken(); + if (token.value != TOK.endOfLine) + break; + auto ret = new AST.ReturnStatement(exp.loc, exp); + auto parameterList = AST.ParameterList(new AST.Parameters(), VarArg.none, 0); + StorageClass stc = STC.auto_; + auto tf = new AST.TypeFunction(parameterList, null, LINK.d, stc); + auto fd = new AST.FuncDeclaration(exp.loc, exp.loc, id, stc, tf, 0); + fd.fbody = ret; + AST.Dsymbols* decldefs = new AST.Dsymbols(); + decldefs.push(fd); + AST.TemplateParameters* tpl = new AST.TemplateParameters(); + AST.Expression constraint = null; + auto tempdecl = new AST.TemplateDeclaration(exp.loc, id, tpl, constraint, decldefs, false); + addVar(tempdecl); + nextDefineLine(); + continue; + default: break; } @@ -5911,8 +5948,8 @@ final class CParser(AST) : Parser!AST } else { - scan(&n); - if (n.value != TOK.endOfLine) + scan(&token); + if (token.value != TOK.endOfLine) { skipToNextLine(); } @@ -5920,6 +5957,7 @@ final class CParser(AST) : Parser!AST nextDefineLine(); } + eSink = save; defines = buf; } diff --git a/dmd/errorsink.d b/dmd/errorsink.d index ce2351738d6..3811f1d2932 100644 --- a/dmd/errorsink.d +++ b/dmd/errorsink.d @@ -60,6 +60,20 @@ class ErrorSinkNull : ErrorSink void deprecationSupplemental(const ref Loc loc, const(char)* format, ...) { } } +/***************************************** + * Ignores the messages, but sets `sawErrors` for any calls to `error()` + */ +class ErrorSinkLatch : ErrorSinkNull +{ + nothrow: + extern (C++): + override: + + bool sawErrors; + + void error(const ref Loc loc, const(char)* format, ...) { sawErrors = true; } +} + /***************************************** * Simplest implementation, just sends messages to stderr. * See also: ErrorSinkCompiler. diff --git a/dmd/lexer.d b/dmd/lexer.d index 2f541430ac7..af5a745afb2 100644 --- a/dmd/lexer.d +++ b/dmd/lexer.d @@ -3263,7 +3263,7 @@ class Lexer while (1) { printf("%s ", (*tk).toChars()); - if (tk.value == TOK.endOfFile) + if (tk.value == TOK.endOfFile || tk.value == TOK.endOfLine) break; tk = peek(tk); } diff --git a/tests/dmd/compilable/imports/defines.c b/tests/dmd/compilable/imports/defines.c index 6bd07366544..8a5601a2d08 100644 --- a/tests/dmd/compilable/imports/defines.c +++ b/tests/dmd/compilable/imports/defines.c @@ -26,3 +26,7 @@ _Static_assert(F80 == 9.0L, "9"); #define SSS "hello" _Static_assert(SSS[0] == 'h', "10"); + +#define ABC 12 +#define GHI (size) abbadabba +#define DEF (ABC + 5) diff --git a/tests/dmd/compilable/testdefines.d b/tests/dmd/compilable/testdefines.d index 4507266c751..9dd8cf2af8d 100644 --- a/tests/dmd/compilable/testdefines.d +++ b/tests/dmd/compilable/testdefines.d @@ -12,3 +12,6 @@ static assert(F64 == 8.0); static assert(F80 == 9.0L); static assert(SSS == "hello"); + +static assert(ABC == 12); +static assert(DEF == 17); From 445af32a32cf2b3bdde181b446d39e4eac310a00 Mon Sep 17 00:00:00 2001 From: Razvan Nitu Date: Tue, 5 Dec 2023 15:01:03 +0200 Subject: [PATCH 077/215] Move dmd.aliasthis.resolveAliasThis to dsymbolsem (dlang/dmd!15885) --- dmd/aliasthis.d | 132 +---------------------------------------------- dmd/dcast.d | 1 + dmd/dsymbolsem.d | 122 +++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 124 insertions(+), 131 deletions(-) diff --git a/dmd/aliasthis.d b/dmd/aliasthis.d index a8933f6d2fe..1c72fe4b614 100644 --- a/dmd/aliasthis.d +++ b/dmd/aliasthis.d @@ -14,16 +14,11 @@ module dmd.aliasthis; import core.stdc.stdio; -import dmd.aggregate; -import dmd.dscope; + import dmd.dsymbol; -import dmd.expression; -import dmd.expressionsem; -import dmd.globals; import dmd.identifier; import dmd.location; import dmd.mtype; -import dmd.tokens; import dmd.visitor; /*********************************************************** @@ -72,131 +67,6 @@ extern (C++) final class AliasThis : Dsymbol } } -/************************************* - * Find the `alias this` symbol of e's type. - * Params: - * sc = context - * e = expression forming the `this` - * gag = do not print errors, return `null` instead - * findOnly = don't do further processing like resolving properties, - * i.e. just return plain dotExp() result. - * Returns: - * Expression that is `e.aliasthis` - */ -Expression resolveAliasThis(Scope* sc, Expression e, bool gag = false, bool findOnly = false) -{ - import dmd.typesem : dotExp; - for (AggregateDeclaration ad = isAggregate(e.type); ad;) - { - if (ad.aliasthis) - { - Loc loc = e.loc; - Type tthis = (e.op == EXP.type ? e.type : null); - const flags = cast(DotExpFlag) (DotExpFlag.noAliasThis | (gag * DotExpFlag.gag)); - uint olderrors = gag ? global.startGagging() : 0; - e = dotExp(ad.type, sc, e, ad.aliasthis.ident, flags); - if (!e || findOnly) - return gag && global.endGagging(olderrors) ? null : e; - - if (tthis && ad.aliasthis.sym.needThis()) - { - if (auto ve = e.isVarExp()) - { - if (auto fd = ve.var.isFuncDeclaration()) - { - // https://issues.dlang.org/show_bug.cgi?id=13009 - // Support better match for the overloaded alias this. - bool hasOverloads; - if (auto f = fd.overloadModMatch(loc, tthis, hasOverloads)) - { - if (!hasOverloads) - fd = f; // use exact match - e = new VarExp(loc, fd, hasOverloads); - e.type = f.type; - e = new CallExp(loc, e); - goto L1; - } - } - } - /* non-@property function is not called inside typeof(), - * so resolve it ahead. - */ - { - int save = sc.intypeof; - sc.intypeof = 1; // bypass "need this" error check - e = resolveProperties(sc, e); - sc.intypeof = save; - } - L1: - e = new TypeExp(loc, new TypeTypeof(loc, e)); - e = e.expressionSemantic(sc); - } - e = resolveProperties(sc, e); - if (!gag) - ad.aliasthis.checkDeprecatedAliasThis(loc, sc); - else if (global.endGagging(olderrors)) - e = null; - } - - import dmd.dclass : ClassDeclaration; - auto cd = ad.isClassDeclaration(); - if ((!e || !ad.aliasthis) && cd && cd.baseClass && cd.baseClass != ClassDeclaration.object) - { - ad = cd.baseClass; - continue; - } - break; - } - return e; -} - -/** - * Check if an `alias this` is deprecated - * - * Usually one would use `expression.checkDeprecated(scope, aliasthis)` to - * check if `expression` uses a deprecated `aliasthis`, but this calls - * `toPrettyChars` which lead to the following message: - * "Deprecation: alias this `fullyqualified.aggregate.__anonymous` is deprecated" - * - * Params: - * at = The `AliasThis` object to check - * loc = `Loc` of the expression triggering the access to `at` - * sc = `Scope` of the expression - * (deprecations do not trigger in deprecated scopes) - * - * Returns: - * Whether the alias this was reported as deprecated. - */ -bool checkDeprecatedAliasThis(AliasThis at, const ref Loc loc, Scope* sc) -{ - import dmd.errors : deprecation, Classification; - import dmd.dsymbolsem : getMessage; - - if (global.params.useDeprecated != DiagnosticReporting.off - && at.isDeprecated() && !sc.isDeprecated()) - { - const(char)* message = null; - for (Dsymbol p = at; p; p = p.parent) - { - message = p.depdecl ? p.depdecl.getMessage() : null; - if (message) - break; - } - if (message) - deprecation(loc, "`alias %s this` is deprecated - %s", - at.sym.toChars(), message); - else - deprecation(loc, "`alias %s this` is deprecated", - at.sym.toChars()); - - if (auto ti = sc.parent ? sc.parent.isInstantiated() : null) - ti.printInstantiationTrace(Classification.deprecation); - - return true; - } - return false; -} - /************************************** * Check and set 'att' if 't' is a recursive 'alias this' type * diff --git a/dmd/dcast.d b/dmd/dcast.d index bb86b080be6..cfa374c970b 100644 --- a/dmd/dcast.d +++ b/dmd/dcast.d @@ -24,6 +24,7 @@ import dmd.dinterpret; import dmd.dscope; import dmd.dstruct; import dmd.dsymbol; +import dmd.dsymbolsem; import dmd.errors; import dmd.escape; import dmd.expression; diff --git a/dmd/dsymbolsem.d b/dmd/dsymbolsem.d index 060abfe1896..2f71af8d522 100644 --- a/dmd/dsymbolsem.d +++ b/dmd/dsymbolsem.d @@ -304,6 +304,128 @@ bool checkHasBothRvalueAndCpCtor(StructDeclaration sd, CtorDeclaration ctor, Tem return false; } +/************************************* + * Find the `alias this` symbol of e's type. + * Params: + * sc = context + * e = expression forming the `this` + * gag = do not print errors, return `null` instead + * findOnly = don't do further processing like resolving properties, + * i.e. just return plain dotExp() result. + * Returns: + * Expression that is `e.aliasthis` + */ +Expression resolveAliasThis(Scope* sc, Expression e, bool gag = false, bool findOnly = false) +{ + import dmd.typesem : dotExp; + for (AggregateDeclaration ad = isAggregate(e.type); ad;) + { + if (ad.aliasthis) + { + Loc loc = e.loc; + Type tthis = (e.op == EXP.type ? e.type : null); + const flags = cast(DotExpFlag) (DotExpFlag.noAliasThis | (gag * DotExpFlag.gag)); + uint olderrors = gag ? global.startGagging() : 0; + e = dotExp(ad.type, sc, e, ad.aliasthis.ident, flags); + if (!e || findOnly) + return gag && global.endGagging(olderrors) ? null : e; + + if (tthis && ad.aliasthis.sym.needThis()) + { + if (auto ve = e.isVarExp()) + { + if (auto fd = ve.var.isFuncDeclaration()) + { + // https://issues.dlang.org/show_bug.cgi?id=13009 + // Support better match for the overloaded alias this. + bool hasOverloads; + if (auto f = fd.overloadModMatch(loc, tthis, hasOverloads)) + { + if (!hasOverloads) + fd = f; // use exact match + e = new VarExp(loc, fd, hasOverloads); + e.type = f.type; + e = new CallExp(loc, e); + goto L1; + } + } + } + /* non-@property function is not called inside typeof(), + * so resolve it ahead. + */ + { + int save = sc.intypeof; + sc.intypeof = 1; // bypass "need this" error check + e = resolveProperties(sc, e); + sc.intypeof = save; + } + L1: + e = new TypeExp(loc, new TypeTypeof(loc, e)); + e = e.expressionSemantic(sc); + } + e = resolveProperties(sc, e); + if (!gag) + ad.aliasthis.checkDeprecatedAliasThis(loc, sc); + else if (global.endGagging(olderrors)) + e = null; + } + + import dmd.dclass : ClassDeclaration; + auto cd = ad.isClassDeclaration(); + if ((!e || !ad.aliasthis) && cd && cd.baseClass && cd.baseClass != ClassDeclaration.object) + { + ad = cd.baseClass; + continue; + } + break; + } + return e; +} + +/** + * Check if an `alias this` is deprecated + * + * Usually one would use `expression.checkDeprecated(scope, aliasthis)` to + * check if `expression` uses a deprecated `aliasthis`, but this calls + * `toPrettyChars` which lead to the following message: + * "Deprecation: alias this `fullyqualified.aggregate.__anonymous` is deprecated" + * + * Params: + * at = The `AliasThis` object to check + * loc = `Loc` of the expression triggering the access to `at` + * sc = `Scope` of the expression + * (deprecations do not trigger in deprecated scopes) + * + * Returns: + * Whether the alias this was reported as deprecated. + */ +private bool checkDeprecatedAliasThis(AliasThis at, const ref Loc loc, Scope* sc) +{ + if (global.params.useDeprecated != DiagnosticReporting.off + && at.isDeprecated() && !sc.isDeprecated()) + { + const(char)* message = null; + for (Dsymbol p = at; p; p = p.parent) + { + message = p.depdecl ? p.depdecl.getMessage() : null; + if (message) + break; + } + if (message) + deprecation(loc, "`alias %s this` is deprecated - %s", + at.sym.toChars(), message); + else + deprecation(loc, "`alias %s this` is deprecated", + at.sym.toChars()); + + if (auto ti = sc.parent ? sc.parent.isInstantiated() : null) + ti.printInstantiationTrace(Classification.deprecation); + + return true; + } + return false; +} + private extern(C++) final class DsymbolSemanticVisitor : Visitor { alias visit = Visitor.visit; From 4f182ec8c803b649cbedaa2526cfd7b1cb00a59c Mon Sep 17 00:00:00 2001 From: Razvan Nitu Date: Tue, 5 Dec 2023 15:01:51 +0200 Subject: [PATCH 078/215] Delete useless imports from compiler/src/dmd/init.d (dlang/dmd!15884) --- dmd/init.d | 6 ------ 1 file changed, 6 deletions(-) diff --git a/dmd/init.d b/dmd/init.d index e48410082bd..5aefb0048a6 100644 --- a/dmd/init.d +++ b/dmd/init.d @@ -12,21 +12,15 @@ module dmd.init; import core.stdc.stdio; -import core.checkedint; import dmd.arraytypes; import dmd.astenums; import dmd.ast_node; -import dmd.dsymbol; import dmd.expression; -import dmd.globals; -import dmd.hdrgen; import dmd.identifier; import dmd.location; import dmd.mtype; -import dmd.common.outbuffer; import dmd.rootobject; -import dmd.tokens; import dmd.visitor; enum NeedInterpret : int From 21ce16e45ac93a2d46622ff7cb8c433eb9d7da67 Mon Sep 17 00:00:00 2001 From: RazvanN7 Date: Tue, 5 Dec 2023 13:46:47 +0200 Subject: [PATCH 079/215] Move dmd.aliasthis.isRecursiveAliasThis to mtype.d --- dmd/aliasthis.d | 34 ---------------------------------- dmd/mtype.d | 33 +++++++++++++++++++++++++++++++++ 2 files changed, 33 insertions(+), 34 deletions(-) diff --git a/dmd/aliasthis.d b/dmd/aliasthis.d index 1c72fe4b614..0c156360fdc 100644 --- a/dmd/aliasthis.d +++ b/dmd/aliasthis.d @@ -18,7 +18,6 @@ import core.stdc.stdio; import dmd.dsymbol; import dmd.identifier; import dmd.location; -import dmd.mtype; import dmd.visitor; /*********************************************************** @@ -66,36 +65,3 @@ extern (C++) final class AliasThis : Dsymbol return this.isDeprecated_; } } - -/************************************** - * Check and set 'att' if 't' is a recursive 'alias this' type - * - * The goal is to prevent endless loops when there is a cycle in the alias this chain. - * Since there is no multiple `alias this`, the chain either ends in a leaf, - * or it loops back on itself as some point. - * - * Example: S0 -> (S1 -> S2 -> S3 -> S1) - * - * `S0` is not a recursive alias this, so this returns `false`, and a rewrite to `S1` can be tried. - * `S1` is a recursive alias this type, but since `att` is initialized to `null`, - * this still returns `false`, but `att1` is set to `S1`. - * A rewrite to `S2` and `S3` can be tried, but when we want to try a rewrite to `S1` again, - * we notice `att == t`, so we're back at the start of the loop, and this returns `true`. - * - * Params: - * att = type reference used to detect recursion. Should be initialized to `null`. - * t = type of 'alias this' rewrite to attempt - * - * Returns: - * `false` if the rewrite is safe, `true` if it would loop back around - */ -bool isRecursiveAliasThis(ref Type att, Type t) -{ - //printf("+isRecursiveAliasThis(att = %s, t = %s)\n", att ? att.toChars() : "null", t.toChars()); - auto tb = t.toBasetype(); - if (att && tb.equivalent(att)) - return true; - else if (!att && tb.checkAliasThisRec()) - att = tb; - return false; -} diff --git a/dmd/mtype.d b/dmd/mtype.d index 8860f143715..9b96bf50dc7 100644 --- a/dmd/mtype.d +++ b/dmd/mtype.d @@ -7738,3 +7738,36 @@ TypeIdentifier getException() tid.addIdent(Id.Exception); return tid; } + +/************************************** + * Check and set 'att' if 't' is a recursive 'alias this' type + * + * The goal is to prevent endless loops when there is a cycle in the alias this chain. + * Since there is no multiple `alias this`, the chain either ends in a leaf, + * or it loops back on itself as some point. + * + * Example: S0 -> (S1 -> S2 -> S3 -> S1) + * + * `S0` is not a recursive alias this, so this returns `false`, and a rewrite to `S1` can be tried. + * `S1` is a recursive alias this type, but since `att` is initialized to `null`, + * this still returns `false`, but `att1` is set to `S1`. + * A rewrite to `S2` and `S3` can be tried, but when we want to try a rewrite to `S1` again, + * we notice `att == t`, so we're back at the start of the loop, and this returns `true`. + * + * Params: + * att = type reference used to detect recursion. Should be initialized to `null`. + * t = type of 'alias this' rewrite to attempt + * + * Returns: + * `false` if the rewrite is safe, `true` if it would loop back around + */ +bool isRecursiveAliasThis(ref Type att, Type t) +{ + //printf("+isRecursiveAliasThis(att = %s, t = %s)\n", att ? att.toChars() : "null", t.toChars()); + auto tb = t.toBasetype(); + if (att && tb.equivalent(att)) + return true; + else if (!att && tb.checkAliasThisRec()) + att = tb; + return false; +} From 911f0c0136363606c4bb468f7ee8c0c79437c162 Mon Sep 17 00:00:00 2001 From: Walter Bright Date: Wed, 6 Dec 2023 00:00:48 -0800 Subject: [PATCH 080/215] Dscope.search: use out parameter --- dmd/doc.d | 9 ++++++--- dmd/dscope.d | 21 +++++++++------------ dmd/dsymbolsem.d | 8 +++++--- dmd/dtemplate.d | 2 +- dmd/expressionsem.d | 14 +++++++++----- dmd/frontend.h | 2 +- dmd/lambdacomp.d | 2 +- dmd/semantic3.d | 3 ++- dmd/statementsem.d | 3 ++- dmd/typesem.d | 6 +++--- 10 files changed, 39 insertions(+), 31 deletions(-) diff --git a/dmd/doc.d b/dmd/doc.d index 5488d5a0008..3f9b0c250f2 100644 --- a/dmd/doc.d +++ b/dmd/doc.d @@ -748,7 +748,8 @@ void emitAnchor(ref OutBuffer buf, Dsymbol s, Scope* sc, bool forHeader = false) auto a = imp.aliases[i]; auto id = a ? a : imp.names[i]; auto loc = Loc.init; - if (auto symFromId = sc.search(loc, id, null)) + Dsymbol pscopesym; + if (auto symFromId = sc.search(loc, id, pscopesym)) { emitAnchor(buf, symFromId, sc, forHeader); } @@ -3636,7 +3637,8 @@ struct MarkdownLinkReferences if (id) { auto loc = Loc(); - auto symbol = _scope.search(loc, id, null, IgnoreErrors); + Dsymbol pscopesym; + auto symbol = _scope.search(loc, id, pscopesym, IgnoreErrors); for (size_t i = 1; symbol && i < ids.length; ++i) { id = Identifier.lookup(ids[i].ptr, ids[i].length); @@ -4997,7 +4999,8 @@ void highlightCode(Scope* sc, Dsymbol s, ref OutBuffer buf, size_t offset) auto a = imp.aliases[i]; auto id = a ? a : imp.names[i]; auto loc = Loc.init; - if (auto symFromId = sc.search(loc, id, null)) + Dsymbol pscopesym; + if (auto symFromId = sc.search(loc, id, pscopesym)) { highlightCode(sc, symFromId, buf, offset); } diff --git a/dmd/dscope.d b/dmd/dscope.d index d68bcdaad40..e4e1c389752 100644 --- a/dmd/dscope.d +++ b/dmd/dscope.d @@ -344,13 +344,13 @@ extern (C++) struct Scope * Params: * loc = location to use for error messages * ident = name to look up - * pscopesym = if supplied and name is found, set to scope that ident was found in + * pscopesym = if supplied and name is found, set to scope that ident was found in, otherwise set to null * flags = modify search based on flags * * Returns: * symbol if found, null if not */ - extern (C++) Dsymbol search(const ref Loc loc, Identifier ident, Dsymbol* pscopesym, int flags = IgnoreNone) + extern (C++) Dsymbol search(const ref Loc loc, Identifier ident, out Dsymbol pscopesym, int flags = IgnoreNone) { version (LOGSEARCH) { @@ -386,8 +386,7 @@ extern (C++) struct Scope if (Dsymbol s = sc.scopesym.isModule()) { //printMsg("\tfound", s); - if (pscopesym) - *pscopesym = sc.scopesym; + pscopesym = sc.scopesym; return s; } } @@ -486,8 +485,7 @@ extern (C++) struct Scope } } //printMsg("\tfound local", s); - if (pscopesym) - *pscopesym = sc.scopesym; + pscopesym = sc.scopesym; return s; } @@ -499,8 +497,7 @@ extern (C++) struct Scope if (aliasSym) { //printf("found aliassym: %s\n", aliasSym.toChars()); - if (pscopesym) - *pscopesym = new ExpressionDsymbol(exp); + pscopesym = new ExpressionDsymbol(exp); return aliasSym; } } @@ -554,8 +551,8 @@ extern (C++) struct Scope return null; Scope* sc = &this; Module.clearCache(); - Dsymbol scopesym = null; - Dsymbol s = sc.search(Loc.initial, id, &scopesym, IgnoreErrors); + Dsymbol scopesym; + Dsymbol s = sc.search(Loc.initial, id, scopesym, IgnoreErrors); if (!s) return null; @@ -579,9 +576,9 @@ extern (C++) struct Scope return s; } - Dsymbol scopesym = null; + Dsymbol scopesym; // search for exact name first - if (auto s = search(Loc.initial, ident, &scopesym, IgnoreErrors)) + if (auto s = search(Loc.initial, ident, scopesym, IgnoreErrors)) return s; return speller!scope_search_fp(ident.toString()); } diff --git a/dmd/dsymbolsem.d b/dmd/dsymbolsem.d index 2f71af8d522..30b72c2d4f0 100644 --- a/dmd/dsymbolsem.d +++ b/dmd/dsymbolsem.d @@ -481,7 +481,8 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor Dsymbol s = ad.search(dsym.loc, dsym.ident); if (!s) { - s = sc.search(dsym.loc, dsym.ident, null); + Dsymbol pscopesym; + s = sc.search(dsym.loc, dsym.ident, pscopesym); if (s) error(dsym.loc, "`%s` is not a member of `%s`", s.toChars(), ad.toChars()); else @@ -4243,7 +4244,8 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor // check if `_d_cmain` is defined bool cmainTemplateExists() { - auto rootSymbol = sc.search(funcdecl.loc, Id.empty, null); + Dsymbol pscopesym; + auto rootSymbol = sc.search(funcdecl.loc, Id.empty, pscopesym); if (auto moduleSymbol = rootSymbol.search(funcdecl.loc, Id.object)) if (moduleSymbol.search(funcdecl.loc, Id.CMain)) return true; @@ -7328,7 +7330,7 @@ private void aliasAssignSemantic(AliasAssign ds, Scope* sc) AliasDeclaration findAliasDeclaration(AliasAssign ds, Scope* sc) { Dsymbol scopesym; - Dsymbol as = sc.search(ds.loc, ds.ident, &scopesym); + Dsymbol as = sc.search(ds.loc, ds.ident, scopesym); if (!as) { .error(ds.loc, "%s `%s` undefined identifier `%s`", ds.kind, ds.toPrettyChars, ds.ident.toChars()); diff --git a/dmd/dtemplate.d b/dmd/dtemplate.d index 326d66364b8..360628ce3c2 100644 --- a/dmd/dtemplate.d +++ b/dmd/dtemplate.d @@ -6465,7 +6465,7 @@ extern (C++) class TemplateInstance : ScopeDsymbol */ Identifier id = name; Dsymbol scopesym; - Dsymbol s = sc.search(loc, id, &scopesym); + Dsymbol s = sc.search(loc, id, scopesym); if (!s) { s = sc.search_correct(id); diff --git a/dmd/expressionsem.d b/dmd/expressionsem.d index 1664bf22dca..24a3974fc65 100644 --- a/dmd/expressionsem.d +++ b/dmd/expressionsem.d @@ -3743,7 +3743,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor } Dsymbol scopesym; - Dsymbol s = sc.search(exp.loc, exp.ident, &scopesym); + Dsymbol s = sc.search(exp.loc, exp.ident, scopesym); if (s) { if (s.errors) @@ -6744,7 +6744,8 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor if (!sc.insert(s)) { - auto conflict = sc.search(Loc.initial, s.ident, null); + Dsymbol pscopesym; + auto conflict = sc.search(Loc.initial, s.ident, pscopesym); error(e.loc, "declaration `%s` is already defined", s.toPrettyChars()); errorSupplemental(conflict.loc, "`%s` `%s` is defined here", conflict.kind(), conflict.toChars()); @@ -6986,7 +6987,8 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor */ if (!tup && !sc.insert(s)) { - auto conflict = sc.search(Loc.initial, s.ident, null); + Dsymbol pscopesym; + auto conflict = sc.search(Loc.initial, s.ident, pscopesym); error(e.loc, "declaration `%s` is already defined", s.toPrettyChars()); errorSupplemental(conflict.loc, "`%s` `%s` is defined here", conflict.kind(), conflict.toChars()); @@ -7293,7 +7295,8 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor s.dsymbolSemantic(sc); if (!sc.insert(s)) { - auto conflict = sc.search(Loc.initial, s.ident, null); + Dsymbol pscopesym; + auto conflict = sc.search(Loc.initial, s.ident, pscopesym); error(e.loc, "declaration `%s` is already defined", s.toPrettyChars()); errorSupplemental(conflict.loc, "`%s` `%s` is defined here", conflict.kind(), conflict.toChars()); @@ -16038,7 +16041,8 @@ VarDeclaration makeThis2Argument(const ref Loc loc, Scope* sc, FuncDeclaration f */ bool verifyHookExist(const ref Loc loc, ref Scope sc, Identifier id, string description, Identifier module_ = Id.object) { - auto rootSymbol = sc.search(loc, Id.empty, null); + Dsymbol pscopesym; + auto rootSymbol = sc.search(loc, Id.empty, pscopesym); if (auto moduleSymbol = rootSymbol.search(loc, module_)) if (moduleSymbol.search(loc, id)) return true; diff --git a/dmd/frontend.h b/dmd/frontend.h index c37554168fd..35e1450b190 100644 --- a/dmd/frontend.h +++ b/dmd/frontend.h @@ -6342,7 +6342,7 @@ struct Scope final void* anchorCounts; Identifier* prevAnchor; AliasDeclaration* aliasAsg; - Dsymbol* search(const Loc& loc, Identifier* ident, Dsymbol** pscopesym, int32_t flags = 0); + Dsymbol* search(const Loc& loc, Identifier* ident, Dsymbol*& pscopesym, int32_t flags = 0); Scope() : enclosing(), _module(), diff --git a/dmd/lambdacomp.d b/dmd/lambdacomp.d index d19d435f240..c90c36069fd 100644 --- a/dmd/lambdacomp.d +++ b/dmd/lambdacomp.d @@ -244,7 +244,7 @@ public: { // we must check what the identifier expression is. Dsymbol scopesym; - Dsymbol s = sc.search(exp.loc, exp.ident, &scopesym); + Dsymbol s = sc.search(exp.loc, exp.ident, scopesym); if (s) { auto v = s.isVarDeclaration(); diff --git a/dmd/semantic3.d b/dmd/semantic3.d index c255701d767..7498eaf4458 100644 --- a/dmd/semantic3.d +++ b/dmd/semantic3.d @@ -520,7 +520,8 @@ private extern(C++) final class Semantic3Visitor : Visitor { Parameter narg = Parameter.getNth(t.arguments, j); assert(narg.ident); - VarDeclaration v = sc2.search(Loc.initial, narg.ident, null).isVarDeclaration(); + Dsymbol pscopesym; + VarDeclaration v = sc2.search(Loc.initial, narg.ident, pscopesym).isVarDeclaration(); assert(v); (*exps)[j] = new VarExp(v.loc, v); } diff --git a/dmd/statementsem.d b/dmd/statementsem.d index 3873adc82ee..b000f7d3191 100644 --- a/dmd/statementsem.d +++ b/dmd/statementsem.d @@ -2261,7 +2261,8 @@ Statement statementSemanticVisit(Statement s, Scope* sc) continue; assert(scx.sw == sw); - if (!scx.search(cs.exp.loc, v.ident, null)) + Dsymbol pscopesym; + if (!scx.search(cs.exp.loc, v.ident, pscopesym)) { error(cs.loc, "`case` variable `%s` declared at %s cannot be declared in `switch` body", v.toChars(), v.loc.toChars()); diff --git a/dmd/typesem.d b/dmd/typesem.d index 2063a954b99..aa23bc2f335 100644 --- a/dmd/typesem.d +++ b/dmd/typesem.d @@ -1878,7 +1878,7 @@ extern(C++) Type typeSemantic(Type type, const ref Loc loc, Scope* sc) /* look for pre-existing declaration */ Dsymbol scopesym; - auto s = sc2.search(mtype.loc, mtype.id, &scopesym, IgnoreErrors | TagNameSpace); + auto s = sc2.search(mtype.loc, mtype.id, scopesym, IgnoreErrors | TagNameSpace); if (!s || s.isModule()) { // no pre-existing declaration, so declare it @@ -2753,7 +2753,7 @@ void resolve(Type mt, const ref Loc loc, Scope* sc, out Expression pe, out Type } Dsymbol scopesym; - Dsymbol s = sc.search(loc, mt.ident, &scopesym); + Dsymbol s = sc.search(loc, mt.ident, scopesym); /* * https://issues.dlang.org/show_bug.cgi?id=1170 * https://issues.dlang.org/show_bug.cgi?id=10739 @@ -2776,7 +2776,7 @@ void resolve(Type mt, const ref Loc loc, Scope* sc, out Expression pe, out Type mixinTempl.dsymbolSemantic(sc); } sds.members.foreachDsymbol( s => semanticOnMixin(s) ); - s = sc.search(loc, mt.ident, &scopesym); + s = sc.search(loc, mt.ident, scopesym); } } From b02da921ea23430a33f9a2009b1a7b902e23fcd0 Mon Sep 17 00:00:00 2001 From: Dennis Korpel Date: Thu, 7 Dec 2023 11:29:34 +0100 Subject: [PATCH 081/215] Fix 24272 - operations.arrayOp is forced @nogc nothrow pure --- .../src/core/internal/array/operations.d | 35 ++++++++++++++----- 1 file changed, 26 insertions(+), 9 deletions(-) diff --git a/runtime/druntime/src/core/internal/array/operations.d b/runtime/druntime/src/core/internal/array/operations.d index 3e2331484b3..7e5b5f43e9b 100644 --- a/runtime/druntime/src/core/internal/array/operations.d +++ b/runtime/druntime/src/core/internal/array/operations.d @@ -33,7 +33,7 @@ version (LDC) version = GNU_OR_LDC; * * Returns: the slice containing the result */ -T[] arrayOp(T : T[], Args...)(T[] res, Filter!(isType, Args) args) @trusted @nogc pure nothrow +T[] arrayOp(T : T[], Args...)(T[] res, Filter!(isType, Args) args) @trusted { alias scalarizedExp = staticMap!(toElementType, Args); alias check = typeCheck!(true, T, scalarizedExp); // must support all scalar ops @@ -541,7 +541,7 @@ unittest } // test handling of v op= exp -unittest +@nogc nothrow pure @safe unittest { uint[32] c; arrayOp!(uint[], uint, "+=")(c[], 2); @@ -556,7 +556,7 @@ unittest } // proper error message for UDT lacking certain ops -unittest +@nogc nothrow pure @safe unittest { static assert(!is(typeof(&arrayOp!(int[4][], int[4], "+=")))); static assert(!is(typeof(&arrayOp!(int[4][], int[4], "u-", "=")))); @@ -585,7 +585,7 @@ unittest } // test mixed type array op -unittest +@nogc nothrow pure @safe unittest { uint[32] a = 0xF; float[32] res = 2.0f; @@ -595,7 +595,7 @@ unittest } // test mixed type array op -unittest +@nogc nothrow pure @safe unittest { static struct S { @@ -613,7 +613,7 @@ unittest } // test scalar after operation argument -unittest +@nogc nothrow pure @safe unittest { float[32] res, a = 2, b = 3; float c = 4; @@ -622,7 +622,7 @@ unittest assert(v == 2 * 3 + 4); } -unittest +@nogc nothrow pure @safe unittest { // https://issues.dlang.org/show_bug.cgi?id=17964 uint bug(){ @@ -635,7 +635,7 @@ unittest } // https://issues.dlang.org/show_bug.cgi?id=19796 -unittest +nothrow pure @safe unittest { double[] data = [0.5]; double[] result; @@ -645,7 +645,7 @@ unittest } // https://issues.dlang.org/show_bug.cgi?id=21110 -unittest +pure unittest { import core.exception; @@ -668,3 +668,20 @@ unittest void func() { dst[] = a[] + b[]; } assertThrown!AssertError(func(), "Array operations with mismatched lengths must throw an error"); } + +// https://issues.dlang.org/show_bug.cgi?id=24272 +unittest +{ + static struct B + { + B opOpAssign(string op)(B other) + { + static int g; + g++; + throw new Exception(""); + } + } + + B[] bArr; + bArr[] += B(); +} From f24afc7f8715c8df8114aced53d32685d68bb5f6 Mon Sep 17 00:00:00 2001 From: Walter Bright Date: Thu, 7 Dec 2023 13:34:49 -0800 Subject: [PATCH 082/215] fix Issue 24266 - ImportC: struct initializer entry gets ignored --- dmd/initsem.d | 4 ++-- tests/dmd/runnable/test24042.c | 17 +++++++++++++++++ 2 files changed, 19 insertions(+), 2 deletions(-) diff --git a/dmd/initsem.d b/dmd/initsem.d index 6d31f956c8e..0a91c393e98 100644 --- a/dmd/initsem.d +++ b/dmd/initsem.d @@ -606,7 +606,7 @@ extern(C++) Initializer initializerSemantic(Initializer init, Scope* sc, ref Typ { import dmd.common.outbuffer; OutBuffer buf; - HdrGenStage hgs; + HdrGenState hgs; toCBuffer(ts.sym, buf, hgs); printf("%s\n", buf.peekChars()); } @@ -849,7 +849,7 @@ extern(C++) Initializer initializerSemantic(Initializer init, Scope* sc, ref Typ { if (fieldi == nfields) break; - if (/*index == 0 && ci.initializerList.length == 1 &&*/ di.initializer.isCInitializer()) + if (index + 1 == ci.initializerList.length && di.initializer.isCInitializer()) { /* Try peeling off this set of { } and see if it works */ diff --git a/tests/dmd/runnable/test24042.c b/tests/dmd/runnable/test24042.c index 529d2397323..c2db46b19d2 100644 --- a/tests/dmd/runnable/test24042.c +++ b/tests/dmd/runnable/test24042.c @@ -45,9 +45,26 @@ void test2() /**************************************/ +// https://issues.dlang.org/show_bug.cgi?id=24266 + +struct S3 +{ + int context[4]; + int id; +}; + +void test3() +{ + struct S3 tn = (struct S3) {{0}, 4}; + assert(tn.id == 4); +} + +/**************************************/ + int main() { test1(); test2(); + test3(); return 0; } From 22f60188a0bd7c77482908c89fbeec0d8a2ee436 Mon Sep 17 00:00:00 2001 From: Walter Bright Date: Thu, 7 Dec 2023 22:56:03 -0800 Subject: [PATCH 083/215] add SearchOpt to enum type (dlang/dmd!15889) --- dmd/astcodegen.d | 2 +- dmd/dclass.d | 2 +- dmd/dmodule.d | 6 ++-- dmd/doc.d | 4 +-- dmd/dscope.d | 22 ++++++------ dmd/dsymbol.d | 25 ++++++------- dmd/dsymbol.h | 31 ++++++++-------- dmd/dsymbolsem.d | 52 +++++++++++++-------------- dmd/dtoh.d | 2 +- dmd/expressionsem.d | 18 +++++----- dmd/frontend.h | 35 ++++++++++-------- dmd/module.h | 4 +-- dmd/scope.h | 2 +- dmd/typesem.d | 18 +++++----- tests/dmd/unit/compilable/searching.d | 2 +- 15 files changed, 116 insertions(+), 109 deletions(-) diff --git a/dmd/astcodegen.d b/dmd/astcodegen.d index d40f836faae..f17907719a7 100644 --- a/dmd/astcodegen.d +++ b/dmd/astcodegen.d @@ -97,6 +97,6 @@ struct ASTCodegen alias isExpression = dmd.dtemplate.isExpression; alias isTuple = dmd.dtemplate.isTuple; - alias IgnoreErrors = dmd.dsymbol.IgnoreErrors; + alias SearchOpt = dmd.dsymbol.SearchOpt; alias PASS = dmd.dsymbol.PASS; } diff --git a/dmd/dclass.d b/dmd/dclass.d index 72b85cfc64e..187a4208729 100644 --- a/dmd/dclass.d +++ b/dmd/dclass.d @@ -614,7 +614,7 @@ extern (C++) class ClassDeclaration : AggregateDeclaration final bool isFuncHidden(FuncDeclaration fd) { //printf("ClassDeclaration.isFuncHidden(class = %s, fd = %s)\n", toChars(), fd.toPrettyChars()); - Dsymbol s = this.search(Loc.initial, fd.ident, IgnoreAmbiguous | IgnoreErrors); + Dsymbol s = this.search(Loc.initial, fd.ident, SearchOpt.ignoreAmbiguous | SearchOpt.ignoreErrors); if (!s) { //printf("not found\n"); diff --git a/dmd/dmodule.d b/dmd/dmodule.d index d096e437cf9..309c2601d26 100644 --- a/dmd/dmodule.d +++ b/dmd/dmodule.d @@ -401,7 +401,7 @@ extern (C++) final class Module : Package Identifier searchCacheIdent; Dsymbol searchCacheSymbol; // cached value of search - int searchCacheFlags; // cached flags + SearchOptFlags searchCacheFlags; // cached flags bool insearch; /** @@ -1021,14 +1021,14 @@ extern (C++) final class Module : Package } } - override bool isPackageAccessible(Package p, Visibility visibility, int flags = 0) + override bool isPackageAccessible(Package p, Visibility visibility, SearchOptFlags flags = SearchOpt.all) { if (insearch) // don't follow import cycles return false; insearch = true; scope (exit) insearch = false; - if (flags & IgnorePrivateImports) + if (flags & SearchOpt.ignorePrivateImports) visibility = Visibility(Visibility.Kind.public_); // only consider public imports return super.isPackageAccessible(p, visibility); } diff --git a/dmd/doc.d b/dmd/doc.d index 3f9b0c250f2..03848c0274b 100644 --- a/dmd/doc.d +++ b/dmd/doc.d @@ -3638,11 +3638,11 @@ struct MarkdownLinkReferences { auto loc = Loc(); Dsymbol pscopesym; - auto symbol = _scope.search(loc, id, pscopesym, IgnoreErrors); + auto symbol = _scope.search(loc, id, pscopesym, SearchOpt.ignoreErrors); for (size_t i = 1; symbol && i < ids.length; ++i) { id = Identifier.lookup(ids[i].ptr, ids[i].length); - symbol = id !is null ? symbol.search(loc, id, IgnoreErrors) : null; + symbol = id !is null ? symbol.search(loc, id, SearchOpt.ignoreErrors) : null; } if (symbol) link = MarkdownLink(createHref(symbol), null, name, symbol); diff --git a/dmd/dscope.d b/dmd/dscope.d index e4e1c389752..cd177a66f50 100644 --- a/dmd/dscope.d +++ b/dmd/dscope.d @@ -350,7 +350,7 @@ extern (C++) struct Scope * Returns: * symbol if found, null if not */ - extern (C++) Dsymbol search(const ref Loc loc, Identifier ident, out Dsymbol pscopesym, int flags = IgnoreNone) + extern (C++) Dsymbol search(const ref Loc loc, Identifier ident, out Dsymbol pscopesym, SearchOptFlags flags = SearchOpt.all) { version (LOGSEARCH) { @@ -371,7 +371,7 @@ extern (C++) struct Scope } // This function is called only for unqualified lookup - assert(!(flags & (SearchLocalsOnly | SearchImportsOnly))); + assert(!(flags & (SearchOpt.localsOnly | SearchOpt.importsOnly))); /* If ident is "start at module scope", only look at module scope */ @@ -393,7 +393,7 @@ extern (C++) struct Scope return null; } - Dsymbol checkAliasThis(AggregateDeclaration ad, Identifier ident, int flags, Expression* exp) + Dsymbol checkAliasThis(AggregateDeclaration ad, Identifier ident, SearchOptFlags flags, Expression* exp) { import dmd.mtype; if (!ad || !ad.aliasthis) @@ -457,7 +457,7 @@ extern (C++) struct Scope return s; } - Dsymbol searchScopes(int flags) + Dsymbol searchScopes(SearchOptFlags flags) { for (Scope* sc = &this; sc; sc = sc.enclosing) { @@ -467,13 +467,13 @@ extern (C++) struct Scope //printf("\tlooking in scopesym '%s', kind = '%s', flags = x%x\n", sc.scopesym.toChars(), sc.scopesym.kind(), flags); if (sc.scopesym.isModule()) - flags |= SearchUnqualifiedModule; // tell Module.search() that SearchLocalsOnly is to be obeyed + flags |= SearchOpt.unqualifiedModule; // tell Module.search() that SearchOpt.localsOnly is to be obeyed else if (sc.flags & SCOPE.Cfile && sc.scopesym.isStructDeclaration()) continue; // C doesn't have struct scope if (Dsymbol s = sc.scopesym.search(loc, ident, flags)) { - if (flags & TagNameSpace) + if (flags & SearchOpt.tagNameSpace) { // ImportC: if symbol is not a tag, look for it in tag table if (!s.isScopeDsymbol()) @@ -510,15 +510,15 @@ extern (C++) struct Scope } if (this.flags & SCOPE.ignoresymbolvisibility) - flags |= IgnoreSymbolVisibility; + flags |= SearchOpt.ignoreVisibility; // First look in local scopes - Dsymbol s = searchScopes(flags | SearchLocalsOnly); + Dsymbol s = searchScopes(flags | SearchOpt.localsOnly); version (LOGSEARCH) if (s) printMsg("-Scope.search() found local", s); if (!s) { // Second look in imported modules - s = searchScopes(flags | SearchImportsOnly); + s = searchScopes(flags | SearchOpt.importsOnly); version (LOGSEARCH) if (s) printMsg("-Scope.search() found import", s); } return s; @@ -552,7 +552,7 @@ extern (C++) struct Scope Scope* sc = &this; Module.clearCache(); Dsymbol scopesym; - Dsymbol s = sc.search(Loc.initial, id, scopesym, IgnoreErrors); + Dsymbol s = sc.search(Loc.initial, id, scopesym, SearchOpt.ignoreErrors); if (!s) return null; @@ -578,7 +578,7 @@ extern (C++) struct Scope Dsymbol scopesym; // search for exact name first - if (auto s = search(Loc.initial, ident, scopesym, IgnoreErrors)) + if (auto s = search(Loc.initial, ident, scopesym, SearchOpt.ignoreErrors)) return s; return speller!scope_search_fp(ident.toString()); } diff --git a/dmd/dsymbol.d b/dmd/dsymbol.d index 8f5a292a284..89eb9603a00 100644 --- a/dmd/dsymbol.d +++ b/dmd/dsymbol.d @@ -203,20 +203,21 @@ enum PASS : ubyte } // Search options -enum : int +alias SearchOptFlags = uint; +enum SearchOpt : SearchOptFlags { - IgnoreNone = 0x00, // default - IgnorePrivateImports = 0x01, // don't search private imports - IgnoreErrors = 0x02, // don't give error messages - IgnoreAmbiguous = 0x04, // return NULL if ambiguous - SearchLocalsOnly = 0x08, // only look at locals (don't search imports) - SearchImportsOnly = 0x10, // only look in imports - SearchUnqualifiedModule = 0x20, // the module scope search is unqualified, + all = 0x00, // search for all symbols + ignorePrivateImports = 0x01, // don't search private imports + ignoreErrors = 0x02, // don't give error messages + ignoreAmbiguous = 0x04, // return NULL if ambiguous + localsOnly = 0x08, // only look at locals (don't search imports) + importsOnly = 0x10, // only look in imports + unqualifiedModule = 0x20, // the module scope search is unqualified, // meaning don't search imports in that scope, // because qualified module searches search // their imports - IgnoreSymbolVisibility = 0x80, // also find private and package protected symbols - TagNameSpace = 0x100, // search ImportC tag symbol table + tagNameSpace = 0x40, // search ImportC tag symbol table + ignoreVisibility = 0x80, // also find private and package protected symbols } /*********************************************************** @@ -1263,7 +1264,7 @@ public: (*pary)[p.tag] = true; } - bool isPackageAccessible(Package p, Visibility visibility, int flags = 0) nothrow + bool isPackageAccessible(Package p, Visibility visibility, SearchOptFlags flags = SearchOpt.all) nothrow { if (p.tag < accessiblePackages.length && accessiblePackages[p.tag] || visibility.kind == Visibility.Kind.private_ && p.tag < privateAccessiblePackages.length && privateAccessiblePackages[p.tag]) @@ -1272,7 +1273,7 @@ public: { // only search visible scopes && imported modules should ignore private imports if (visibility.kind <= visibilities[i] && - ss.isScopeDsymbol.isPackageAccessible(p, visibility, IgnorePrivateImports)) + ss.isScopeDsymbol.isPackageAccessible(p, visibility, SearchOpt.ignorePrivateImports)) return true; } return false; diff --git a/dmd/dsymbol.h b/dmd/dsymbol.h index 15c997027da..589d00033fc 100644 --- a/dmd/dsymbol.h +++ b/dmd/dsymbol.h @@ -147,20 +147,21 @@ enum /* Flags for symbol search */ -enum +typedef uint SearchOptFlags; +enum class SearchOpt : SearchOptFlags { - IgnoreNone = 0x00, // default - IgnorePrivateImports = 0x01, // don't search private imports - IgnoreErrors = 0x02, // don't give error messages - IgnoreAmbiguous = 0x04, // return NULL if ambiguous - SearchLocalsOnly = 0x08, // only look at locals (don't search imports) - SearchImportsOnly = 0x10, // only look in imports - SearchUnqualifiedModule = 0x20, // the module scope search is unqualified, - // meaning don't search imports in that scope, - // because qualified module searches search - // their imports - IgnoreSymbolVisibility = 0x80, // also find private and package protected symbols - TagNameSpace = 0x100, // search ImportC tag symbol table + all = 0x00, // default + ignorePrivateImports = 0x01, // don't search private imports + ignoreErrors = 0x02, // don't give error messages + ignoreAmbiguous = 0x04, // return NULL if ambiguous + localsOnly = 0x08, // only look at locals (don't search imports) + importsOnly = 0x10, // only look in imports + unqualifiedModule = 0x20, // the module scope search is unqualified, + // meaning don't search imports in that scope, + // because qualified module searches search + // their imports + tagNameSpace = 0x40, // search ImportC tag symbol table + ignoreVisibility = 0x80, // also find private and package protected symbols }; struct FieldState @@ -336,7 +337,7 @@ class ScopeDsymbol : public Dsymbol public: ScopeDsymbol *syntaxCopy(Dsymbol *s) override; virtual void importScope(Dsymbol *s, Visibility visibility); - virtual bool isPackageAccessible(Package *p, Visibility visibility, int flags = 0); + virtual bool isPackageAccessible(Package *p, Visibility visibility, SearchOptFlags flags = (SearchOptFlags)SearchOpt::all); bool isforwardRef() override final; static void multiplyDefined(const Loc &loc, Dsymbol *s1, Dsymbol *s2); const char *kind() const override; @@ -427,6 +428,6 @@ class DsymbolTable final : public RootObject }; void addMember(Dsymbol *dsym, Scope *sc, ScopeDsymbol *sds); -Dsymbol *search(Dsymbol *d, const Loc &loc, Identifier *ident, int flags = SearchLocalsOnly); +Dsymbol *search(Dsymbol *d, const Loc &loc, Identifier *ident, SearchOptFlags flags = (SearchOptFlags)SearchOpt::localsOnly); bool checkDeprecated(Dsymbol *d, const Loc &loc, Scope *sc); void setScope(Dsymbol *d, Scope *sc); diff --git a/dmd/dsymbolsem.d b/dmd/dsymbolsem.d index 30b72c2d4f0..ca6a2edad82 100644 --- a/dmd/dsymbolsem.d +++ b/dmd/dsymbolsem.d @@ -1617,7 +1617,7 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor { AliasDeclaration ad = imp.aliasdecls[i]; //printf("\tImport %s alias %s = %s, scope = %p\n", toPrettyChars(), aliases[i].toChars(), names[i].toChars(), ad._scope); - Dsymbol sym = imp.mod.search(imp.loc, imp.names[i], IgnorePrivateImports); + Dsymbol sym = imp.mod.search(imp.loc, imp.names[i], SearchOpt.ignorePrivateImports); if (sym) { import dmd.access : symbolIsVisible; @@ -7957,11 +7957,11 @@ void checkPrintfScanfSignature(FuncDeclaration funcdecl, TypeFunction f, Scope* * d = dsymbol where ident is searched for * loc = location to print for error messages * ident = identifier to search for - * flags = IgnoreXXXX + * flags = search options * Returns: * null if not found */ -extern(C++) Dsymbol search(Dsymbol d, const ref Loc loc, Identifier ident, int flags = IgnoreNone) +extern(C++) Dsymbol search(Dsymbol d, const ref Loc loc, Identifier ident, SearchOptFlags flags = SearchOpt.all) { scope v = new SearchVisitor(loc, ident, flags); d.accept(v); @@ -7986,13 +7986,13 @@ Dsymbol search_correct(Dsymbol d, Identifier ident) cost = 0; // all the same cost Dsymbol s = d; Module.clearCache(); - return s.search(Loc.initial, id, IgnoreErrors); + return s.search(Loc.initial, id, SearchOpt.ignoreErrors); } if (global.gag) return null; // don't do it for speculative compiles; too time consuming // search for exact name first - if (auto s = d.search(Loc.initial, ident, IgnoreErrors)) + if (auto s = d.search(Loc.initial, ident, SearchOpt.ignoreErrors)) return s; import dmd.root.speller : speller; @@ -8005,10 +8005,10 @@ private extern(C++) class SearchVisitor : Visitor const Loc loc; Identifier ident; - int flags; + SearchOptFlags flags; Dsymbol result; - this(const ref Loc loc, Identifier ident, int flags) + this(const ref Loc loc, Identifier ident, SearchOptFlags flags) { this.loc = loc; this.ident = ident; @@ -8032,7 +8032,7 @@ private extern(C++) class SearchVisitor : Visitor //if (strcmp(ident.toChars(),"c") == 0) *(char*)0=0; // Look in symbols declared in this module - if (sds.symtab && !(flags & SearchImportsOnly)) + if (sds.symtab && !(flags & SearchOpt.importsOnly)) { //printf(" look in locals\n"); auto s1 = sds.symtab.lookup(ident); @@ -8055,30 +8055,30 @@ private extern(C++) class SearchVisitor : Visitor for (size_t i = 0; i < sds.importedScopes.length; i++) { // If private import, don't search it - if ((flags & IgnorePrivateImports) && sds.visibilities[i] == Visibility.Kind.private_) + if ((flags & SearchOpt.ignorePrivateImports) && sds.visibilities[i] == Visibility.Kind.private_) continue; - int sflags = flags & (IgnoreErrors | IgnoreAmbiguous); // remember these in recursive searches + SearchOptFlags sflags = flags & (SearchOpt.ignoreErrors | SearchOpt.ignoreAmbiguous); // remember these in recursive searches Dsymbol ss = (*sds.importedScopes)[i]; //printf("\tscanning import '%s', visibilities = %d, isModule = %p, isImport = %p\n", ss.toChars(), visibilities[i], ss.isModule(), ss.isImport()); if (ss.isModule()) { - if (flags & SearchLocalsOnly) + if (flags & SearchOpt.localsOnly) continue; } else // mixin template { - if (flags & SearchImportsOnly) + if (flags & SearchOpt.importsOnly) continue; - sflags |= SearchLocalsOnly; + sflags |= SearchOpt.localsOnly; } /* Don't find private members if ss is a module */ - Dsymbol s2 = ss.search(loc, ident, sflags | (ss.isModule() ? IgnorePrivateImports : IgnoreNone)); + Dsymbol s2 = ss.search(loc, ident, sflags | (ss.isModule() ? SearchOpt.ignorePrivateImports : SearchOpt.all)); import dmd.access : symbolIsVisible; - if (!s2 || !(flags & IgnoreSymbolVisibility) && !symbolIsVisible(sds, s2)) + if (!s2 || !(flags & SearchOpt.ignoreVisibility) && !symbolIsVisible(sds, s2)) continue; if (!s) { @@ -8149,7 +8149,7 @@ private extern(C++) class SearchVisitor : Visitor } } - if (flags & IgnoreAmbiguous) // if return NULL on ambiguity + if (flags & SearchOpt.ignoreAmbiguous) // if return NULL on ambiguity return setResult(null); /* If two imports from C import files, pick first one, as C has global name space @@ -8157,7 +8157,7 @@ private extern(C++) class SearchVisitor : Visitor if (s.isCsymbol() && s2.isCsymbol()) continue; - if (!(flags & IgnoreErrors)) + if (!(flags & SearchOpt.ignoreErrors)) ScopeDsymbol.multiplyDefined(loc, s, s2); break; } @@ -8184,7 +8184,7 @@ private extern(C++) class SearchVisitor : Visitor override void visit(WithScopeSymbol ws) { //printf("WithScopeSymbol.search(%s)\n", ident.toChars()); - if (flags & SearchImportsOnly) + if (flags & SearchOpt.importsOnly) return setResult(null); // Acts as proxy to the with class declaration Dsymbol s = null; @@ -8425,7 +8425,7 @@ private extern(C++) class SearchVisitor : Visitor if (!ns.members || !ns.symtab) // opaque or semantic() is not yet called { - if (!(flags & IgnoreErrors)) + if (!(flags & SearchOpt.ignoreErrors)) .error(loc, "%s `%s` is forward referenced when looking for `%s`", ns.kind, ns.toPrettyChars, ident.toChars()); return setResult(null); } @@ -8448,7 +8448,7 @@ private extern(C++) class SearchVisitor : Visitor override void visit(Package pkg) { //printf("%s Package.search('%s', flags = x%x)\n", pkg.toChars(), ident.toChars(), flags); - flags &= ~SearchLocalsOnly; // searching an import is always transitive + flags &= ~cast(int)SearchOpt.localsOnly; // searching an import is always transitive if (!pkg.isModule() && pkg.mod) { // Prefer full package name. @@ -8475,8 +8475,8 @@ private extern(C++) class SearchVisitor : Visitor /* Qualified module searches always search their imports, * even if SearchLocalsOnly */ - if (!(flags & SearchUnqualifiedModule)) - flags &= ~(SearchUnqualifiedModule | SearchLocalsOnly); + if (!(flags & SearchOpt.unqualifiedModule)) + flags &= ~(SearchOpt.unqualifiedModule | SearchOpt.localsOnly); if (m.searchCacheIdent == ident && m.searchCacheFlags == flags) { @@ -8525,7 +8525,7 @@ private extern(C++) class SearchVisitor : Visitor if (!sd.members || !sd.symtab) // opaque or semantic() is not yet called { // .stringof is always defined (but may be hidden by some other symbol) - if(ident != Id.stringof && !(flags & IgnoreErrors) && sd.semanticRun < PASS.semanticdone) + if(ident != Id.stringof && !(flags & SearchOpt.ignoreErrors) && sd.semanticRun < PASS.semanticdone) .error(loc, "%s `%s` is forward referenced when looking for `%s`", sd.kind, sd.toPrettyChars, ident.toChars()); return setResult(null); } @@ -8551,7 +8551,7 @@ private extern(C++) class SearchVisitor : Visitor if (!cd.members || !cd.symtab) // opaque or addMember is not yet done { // .stringof is always defined (but may be hidden by some other symbol) - if (ident != Id.stringof && !(flags & IgnoreErrors) && cd.semanticRun < PASS.semanticdone) + if (ident != Id.stringof && !(flags & SearchOpt.ignoreErrors) && cd.semanticRun < PASS.semanticdone) cd.classError("%s `%s` is forward referenced when looking for `%s`", ident.toChars()); //*(char*)0=0; return setResult(null); @@ -8561,7 +8561,7 @@ private extern(C++) class SearchVisitor : Visitor auto s = result; // don't search imports of base classes - if (flags & SearchImportsOnly) + if (flags & SearchOpt.importsOnly) return setResult(s); if (s) @@ -8586,7 +8586,7 @@ private extern(C++) class SearchVisitor : Visitor continue; else if (s == cd) // happens if s is nested in this and derives from this s = null; - else if (!(flags & IgnoreSymbolVisibility) && !(s.visible().kind == Visibility.Kind.protected_) && !symbolIsVisible(cd, s)) + else if (!(flags & SearchOpt.ignoreVisibility) && !(s.visible().kind == Visibility.Kind.protected_) && !symbolIsVisible(cd, s)) s = null; else break; diff --git a/dmd/dtoh.d b/dmd/dtoh.d index 9f855743ef9..ed83a8d9fe1 100644 --- a/dmd/dtoh.d +++ b/dmd/dtoh.d @@ -3284,7 +3284,7 @@ ASTCodegen.Dsymbol symbolFromType(ASTCodegen.Type t) @safe */ ASTCodegen.Dsymbol findMember(ASTCodegen.Dsymbol sym, Identifier name) { - if (auto mem = sym.search(Loc.initial, name, ASTCodegen.IgnoreErrors)) + if (auto mem = sym.search(Loc.initial, name, ASTCodegen.SearchOpt.ignoreErrors)) return mem; // search doesn't work for declarations inside of uninstantiated diff --git a/dmd/expressionsem.d b/dmd/expressionsem.d index 24a3974fc65..c21b382c71e 100644 --- a/dmd/expressionsem.d +++ b/dmd/expressionsem.d @@ -875,7 +875,7 @@ private Expression searchUFCS(Scope* sc, UnaExp ue, Identifier ident) Loc loc = ue.loc; // TODO: merge with Scope.search.searchScopes() - Dsymbol searchScopes(int flags) + Dsymbol searchScopes(SearchOptFlags flags) { Dsymbol s = null; for (Scope* scx = sc; scx; scx = scx.enclosing) @@ -883,7 +883,7 @@ private Expression searchUFCS(Scope* sc, UnaExp ue, Identifier ident) if (!scx.scopesym) continue; if (scx.scopesym.isModule()) - flags |= SearchUnqualifiedModule; // tell Module.search() that SearchLocalsOnly is to be obeyed + flags |= SearchOpt.unqualifiedModule; // tell Module.search() that SearchOpt.localsOnly is to be obeyed s = scx.scopesym.search(loc, ident, flags); if (s) { @@ -910,18 +910,18 @@ private Expression searchUFCS(Scope* sc, UnaExp ue, Identifier ident) return s; } - int flags = 0; + SearchOptFlags flags = SearchOpt.all; Dsymbol s; if (sc.flags & SCOPE.ignoresymbolvisibility) - flags |= IgnoreSymbolVisibility; + flags |= SearchOpt.ignoreVisibility; // First look in local scopes - s = searchScopes(flags | SearchLocalsOnly); + s = searchScopes(flags | SearchOpt.localsOnly); if (!s) { // Second look in imported modules - s = searchScopes(flags | SearchImportsOnly); + s = searchScopes(flags | SearchOpt.importsOnly); } if (!s) @@ -14211,15 +14211,15 @@ Expression dotIdSemanticProp(DotIdExp exp, Scope* sc, bool gag) if (auto ie = eright.isScopeExp()) // also used for template alias's { - auto flags = SearchLocalsOnly; + SearchOptFlags flags = SearchOpt.localsOnly; /* Disable access to another module's private imports. * The check for 'is sds our current module' is because * the current module should have access to its own imports. */ if (ie.sds.isModule() && ie.sds != sc._module) - flags |= IgnorePrivateImports; + flags |= SearchOpt.ignorePrivateImports; if (sc.flags & SCOPE.ignoresymbolvisibility) - flags |= IgnoreSymbolVisibility; + flags |= SearchOpt.ignoreVisibility; Dsymbol s = ie.sds.search(exp.loc, exp.ident, flags); /* Check for visibility before resolving aliases because public * aliases to private symbols are public. diff --git a/dmd/frontend.h b/dmd/frontend.h index 35e1450b190..1dcfbea8213 100644 --- a/dmd/frontend.h +++ b/dmd/frontend.h @@ -624,7 +624,7 @@ class ScopeDsymbol : public Dsymbol public: ScopeDsymbol* syntaxCopy(Dsymbol* s) override; virtual void importScope(Dsymbol* s, Visibility visibility); - virtual bool isPackageAccessible(Package* p, Visibility visibility, int32_t flags = 0); + virtual bool isPackageAccessible(Package* p, Visibility visibility, uint32_t flags = 0u); bool isforwardRef() final override; static void multiplyDefined(const Loc& loc, Dsymbol* s1, Dsymbol* s2); const char* kind() const override; @@ -2064,19 +2064,21 @@ struct FieldState final {} }; -enum +enum class SearchOpt : uint32_t { - IgnoreNone = 0, - IgnorePrivateImports = 1, - IgnoreErrors = 2, - IgnoreAmbiguous = 4, - SearchLocalsOnly = 8, - SearchImportsOnly = 16, - SearchUnqualifiedModule = 32, - IgnoreSymbolVisibility = 128, - TagNameSpace = 256, + all = 0u, + ignorePrivateImports = 1u, + ignoreErrors = 2u, + ignoreAmbiguous = 4u, + localsOnly = 8u, + importsOnly = 16u, + unqualifiedModule = 32u, + tagNameSpace = 64u, + ignoreVisibility = 128u, }; +typedef uint32_t SearchOptFlags; + enum : int32_t { IDX_NOTFOUND = 305419896 }; struct TemplateInstanceBox final @@ -4784,6 +4786,8 @@ struct ASTCodegen final using OverloadSet = ::OverloadSet; using PASS = ::PASS; using ScopeDsymbol = ::ScopeDsymbol; + using SearchOpt = ::SearchOpt; + using SearchOptFlags = ::SearchOptFlags; using Ungag = ::Ungag; using Visibility = ::Visibility; using WithScopeSymbol = ::WithScopeSymbol; @@ -5058,6 +5062,7 @@ struct ASTCodegen final typedef Dsymbol* Dsymbol; typedef Array Dsymbols; typedef Visibility Visibility; + typedef SearchOpt SearchOpt; typedef PASS PASS; ASTCodegen() { @@ -6229,7 +6234,7 @@ class Module final : public Package bool rootImports(); Identifier* searchCacheIdent; Dsymbol* searchCacheSymbol; - int32_t searchCacheFlags; + uint32_t searchCacheFlags; bool insearch; Module* importedFrom; Array* decldefs; @@ -6253,7 +6258,7 @@ class Module final : public Package void importAll(Scope* prevsc) override; int32_t needModuleInfo(); void checkImportDeprecation(const Loc& loc, Scope* sc); - bool isPackageAccessible(Package* p, Visibility visibility, int32_t flags = 0) override; + bool isPackageAccessible(Package* p, Visibility visibility, uint32_t flags = 0u) override; Dsymbol* symtabInsert(Dsymbol* s) override; static void runDeferredSemantic(); static void runDeferredSemantic2(); @@ -6342,7 +6347,7 @@ struct Scope final void* anchorCounts; Identifier* prevAnchor; AliasDeclaration* aliasAsg; - Dsymbol* search(const Loc& loc, Identifier* ident, Dsymbol*& pscopesym, int32_t flags = 0); + Dsymbol* search(const Loc& loc, Identifier* ident, Dsymbol*& pscopesym, uint32_t flags = 0u); Scope() : enclosing(), _module(), @@ -6563,7 +6568,7 @@ extern void dsymbolSemantic(Dsymbol* dsym, Scope* sc); extern void addMember(Dsymbol* dsym, Scope* sc, ScopeDsymbol* sds); -extern Dsymbol* search(Dsymbol* d, const Loc& loc, Identifier* ident, int32_t flags = 0); +extern Dsymbol* search(Dsymbol* d, const Loc& loc, Identifier* ident, uint32_t flags = 0u); extern void setScope(Dsymbol* d, Scope* sc); diff --git a/dmd/module.h b/dmd/module.h index cab0b0a4c1b..8ebac76d6d3 100644 --- a/dmd/module.h +++ b/dmd/module.h @@ -88,7 +88,7 @@ class Module final : public Package Identifier *searchCacheIdent; Dsymbol *searchCacheSymbol; // cached value of search - int searchCacheFlags; // cached flags + SearchOptFlags searchCacheFlags; // cached flags d_bool insearch; // module from command line we're imported from, @@ -123,7 +123,7 @@ class Module final : public Package Module *parse(); // syntactic parse void importAll(Scope *sc) override; int needModuleInfo(); - bool isPackageAccessible(Package *p, Visibility visibility, int flags = 0) override; + bool isPackageAccessible(Package *p, Visibility visibility, SearchOptFlags flags = (SearchOptFlags)SearchOpt::all) override; Dsymbol *symtabInsert(Dsymbol *s) override; static void runDeferredSemantic(); static void runDeferredSemantic2(); diff --git a/dmd/scope.h b/dmd/scope.h index 2cac5f2941b..cceb5a7e3a8 100644 --- a/dmd/scope.h +++ b/dmd/scope.h @@ -130,5 +130,5 @@ struct Scope AliasDeclaration *aliasAsg; // if set, then aliasAsg is being assigned a new value, // do not set wasRead for it - Dsymbol *search(const Loc &loc, Identifier *ident, Dsymbol **pscopesym, int flags = IgnoreNone); + Dsymbol *search(const Loc &loc, Identifier *ident, Dsymbol **pscopesym, SearchOptFlags flags = (SearchOptFlags)SearchOpt::all); }; diff --git a/dmd/typesem.d b/dmd/typesem.d index aa23bc2f335..46500764686 100644 --- a/dmd/typesem.d +++ b/dmd/typesem.d @@ -228,7 +228,7 @@ private void resolveHelper(TypeQualified mt, const ref Loc loc, Scope* sc, Dsymb Type t = s.getType(); // type symbol, type alias, or type tuple? uint errorsave = global.errors; - int flags = t is null ? SearchLocalsOnly : IgnorePrivateImports; + SearchOptFlags flags = t is null ? SearchOpt.localsOnly : SearchOpt.ignorePrivateImports; Dsymbol sm = s.searchX(loc, sc, id, flags); if (sm) @@ -380,12 +380,12 @@ private void resolveHelper(TypeQualified mt, const ref Loc loc, Scope* sc, Dsymb * loc = location to print the error messages * sc = the scope where the symbol is located * id = the id of the symbol - * flags = the search flags which can be `SearchLocalsOnly` or `IgnorePrivateImports` + * flags = the search flags which can be `SearchLocalsOnly` or `SearchOpt.ignorePrivateImports` * * Returns: * symbol found, NULL if not */ -private Dsymbol searchX(Dsymbol dsym, const ref Loc loc, Scope* sc, RootObject id, int flags) +private Dsymbol searchX(Dsymbol dsym, const ref Loc loc, Scope* sc, RootObject id, SearchOptFlags flags) { //printf("Dsymbol::searchX(this=%p,%s, ident='%s')\n", this, toChars(), ident.toChars()); Dsymbol s = dsym.toAlias(); @@ -1878,7 +1878,7 @@ extern(C++) Type typeSemantic(Type type, const ref Loc loc, Scope* sc) /* look for pre-existing declaration */ Dsymbol scopesym; - auto s = sc2.search(mtype.loc, mtype.id, scopesym, IgnoreErrors | TagNameSpace); + auto s = sc2.search(mtype.loc, mtype.id, scopesym, SearchOpt.ignoreErrors | SearchOpt.tagNameSpace); if (!s || s.isModule()) { // no pre-existing declaration, so declare it @@ -3794,8 +3794,8 @@ Expression dotExp(Type mt, Scope* sc, Expression e, Identifier ident, DotExpFlag return e; } - immutable flags = sc.flags & SCOPE.ignoresymbolvisibility ? IgnoreSymbolVisibility : 0; - s = mt.sym.search(e.loc, ident, flags | IgnorePrivateImports); + immutable flags = sc.flags & SCOPE.ignoresymbolvisibility ? SearchOpt.ignoreVisibility : 0; + s = mt.sym.search(e.loc, ident, flags | SearchOpt.ignorePrivateImports); L1: if (!s) { @@ -4074,8 +4074,8 @@ Expression dotExp(Type mt, Scope* sc, Expression e, Identifier ident, DotExpFlag return e; } - int flags = sc.flags & SCOPE.ignoresymbolvisibility ? IgnoreSymbolVisibility : 0; - s = mt.sym.search(e.loc, ident, flags | IgnorePrivateImports); + SearchOptFlags flags = sc.flags & SCOPE.ignoresymbolvisibility ? SearchOpt.ignoreVisibility : SearchOpt.all; + s = mt.sym.search(e.loc, ident, flags | SearchOpt.ignorePrivateImports); L1: if (!s) @@ -4723,7 +4723,7 @@ Type getComplexLibraryType(const ref Loc loc, Scope* sc, TY ty) return *pt; } - Dsymbol s = mConfig.searchX(Loc.initial, sc, id, IgnorePrivateImports); + Dsymbol s = mConfig.searchX(Loc.initial, sc, id, SearchOpt.ignorePrivateImports); if (!s) { error(loc, "`%s` not found in core.stdc.config", id.toChars()); diff --git a/tests/dmd/unit/compilable/searching.d b/tests/dmd/unit/compilable/searching.d index b8ca3d9efc1..5add95dfc8f 100644 --- a/tests/dmd/unit/compilable/searching.d +++ b/tests/dmd/unit/compilable/searching.d @@ -175,7 +175,7 @@ Dsymbol findSymbol(Dsymbol sym, string name, bool allowMissing = false) const oldErrors = global.errors; Identifier id = Identifier.idPool(name); - Dsymbol found = sym.search(Loc.initial, id, IgnoreErrors); + Dsymbol found = sym.search(Loc.initial, id, SearchOpt.ignoreErrors); assert(global.errors == oldErrors, "Searching " ~ name ~ " caused errors!"); assert(allowMissing || found, name ~ " not found!"); From cfe0f95b978fa27cccadfacfcfffae82d4316d44 Mon Sep 17 00:00:00 2001 From: Walter Bright Date: Fri, 8 Dec 2023 00:31:33 -0800 Subject: [PATCH 084/215] fix Issue 24264 - ImportC: inliner trips on _Bool return --- tests/dmd/runnable/cstuff4.c | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) create mode 100644 tests/dmd/runnable/cstuff4.c diff --git a/tests/dmd/runnable/cstuff4.c b/tests/dmd/runnable/cstuff4.c new file mode 100644 index 00000000000..b4984ee4b81 --- /dev/null +++ b/tests/dmd/runnable/cstuff4.c @@ -0,0 +1,25 @@ +// https://issues.dlang.org/show_bug.cgi?id=24264 + +struct S +{ + int small; + int symbol; +}; + +inline int getSym(struct S self) +{ + return self.symbol; +} + +_Bool + symIs0(struct S self) +{ + return getSym(self) == 0; +} + +int main(void) +{ + struct S s = {0, 0}; + __check(symIs0(s)); + return 0; +} From a654e7c424fff0e56ee5d8e6214c7a42d3f339c9 Mon Sep 17 00:00:00 2001 From: "richard (rikki) andrew cattermole" Date: Wed, 15 Nov 2023 19:47:15 +1300 Subject: [PATCH 085/215] Initial attempt at stdatomic.h --- runtime/druntime/src/core/internal/atomic.d | 14 + runtime/druntime/src/core/stdc/stdatomic.d | 1124 +++++++++++++++++++ 2 files changed, 1138 insertions(+) create mode 100644 runtime/druntime/src/core/stdc/stdatomic.d diff --git a/runtime/druntime/src/core/internal/atomic.d b/runtime/druntime/src/core/internal/atomic.d index eebf94ee29d..25b2c70f65a 100644 --- a/runtime/druntime/src/core/internal/atomic.d +++ b/runtime/druntime/src/core/internal/atomic.d @@ -49,6 +49,8 @@ version (DigitalMars) enum SizedReg(int reg, T = size_t) = registerNames[reg][RegIndex!T]; } + enum IsAtomicLockFree(T) = T.sizeof <= size_t.sizeof * 2; + inout(T) atomicLoad(MemoryOrder order = MemoryOrder.seq, T)(inout(T)* src) pure nothrow @nogc @trusted if (CanCAS!T) { @@ -649,6 +651,11 @@ version (DigitalMars) } } + void atomicSignalFence(MemoryOrder order = MemoryOrder.seq)() pure nothrow @nogc @trusted + { + // no-op, dmd doesn't reorder instructions + } + void pause() pure nothrow @nogc @trusted { version (D_InlineAsm_X86) @@ -681,6 +688,8 @@ else version (GNU) import gcc.builtins; import gcc.config; + enum IsAtomicLockFree(T) = __atomic_is_lock_free(T.sizeof, null); + inout(T) atomicLoad(MemoryOrder order = MemoryOrder.seq, T)(inout(T)* src) pure nothrow @nogc @trusted if (CanCAS!T) { @@ -945,6 +954,11 @@ else version (GNU) } } + void atomicSignalFence(MemoryOrder order = MemoryOrder.seq)() pure nothrow @nogc @trusted + { + __atomic_signal_fence(order); + } + void pause() pure nothrow @nogc @trusted { version (X86) diff --git a/runtime/druntime/src/core/stdc/stdatomic.d b/runtime/druntime/src/core/stdc/stdatomic.d new file mode 100644 index 00000000000..6ea47a3189f --- /dev/null +++ b/runtime/druntime/src/core/stdc/stdatomic.d @@ -0,0 +1,1124 @@ +/** + * A D implementation of the C stdatomic.h header. + * + * $(NOTE If it compiles it should produce similar assembly to the system C toolchain + * and should not introduce when optimizing unnecessary behaviors, + * if you do not care about this guarantee use the _impl suffix.) + * + * $(NOTE The D shared type qualifier is the closest to the _Atomic type qualifier from C. It may be changed from shared in the future.) + * + * Copyright: Copyright Richard (Rikki) Andrew Cattermole 2023. + * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) + * Authors: Richard (Rikki) Andrew cattermole + * Source: $(DRUNTIMESRC core/stdc/stdatomic.d) + */ +module core.stdc.stdatomic; +import core.atomic : MemoryOrder; +import core.internal.atomic; +import core.stdc.config; +import core.stdc.stdint; + +@safe nothrow @nogc: + +/// +enum memory_order +{ + /// No ordering provided + memory_order_relaxed = MemoryOrder.raw, + /// As per cppreference.com circa 2015 no compiler supports consume memory order and in practice it devolves to acquire. + memory_order_consume = MemoryOrder.acq, + /// Prevent reordering before operation + memory_order_acquire = MemoryOrder.acq, + /// Prevent reordering after operation + memory_order_release = MemoryOrder.rel, + /// Prevent reordering before and after operation + memory_order_acq_rel = MemoryOrder.acq_rel, + /// Prevent reordering before for read operations and after for writes. + memory_order_seq_cst = MemoryOrder.seq +} + +/// +enum +{ + /// + __STDC_VERSION_STDATOMIC_H__ = 202311, + + /// + ATOMIC_BOOL_LOCK_FREE = IsAtomicLockFree!bool ? 2 : 0, + /// + ATOMIC_CHAR_LOCK_FREE = IsAtomicLockFree!char ? 2 : 0, + /// + ATOMIC_CHAR16_T_LOCK_FREE = IsAtomicLockFree!wchar ? 2 : 0, + /// + ATOMIC_CHAR32_T_LOCK_FREE = IsAtomicLockFree!dchar ? 2 : 0, + /// + ATOMIC_WCHAR_T_LOCK_FREE = ATOMIC_CHAR16_T_LOCK_FREE, + /// + ATOMIC_SHORT_LOCK_FREE = IsAtomicLockFree!short ? 2 : 0, + /// + ATOMIC_INT_LOCK_FREE = IsAtomicLockFree!int ? 2 : 0, + /// + ATOMIC_LONG_LOCK_FREE = IsAtomicLockFree!c_long ? 2 : 0, + /// + ATOMIC_LLONG_LOCK_FREE = IsAtomicLockFree!ulong ? 2 : 0, + /// + ATOMIC_POINTER_LOCK_FREE = IsAtomicLockFree!(void*) ? 2 : 0, + /// + ATOMIC_CHAR8_T_LOCK_FREE = ATOMIC_CHAR_LOCK_FREE, +} + +version (DigitalMars) +{ + alias atomic_signal_fence = atomic_signal_fence_impl; /// + + // these all use inline assembly, so will unlikely produce the codegen a user will expect + version(none) + { + alias atomic_flag_clear = atomic_flag_clear_impl; /// + alias atomic_flag_clear_explicit = atomic_flag_clear_explicit_impl; /// + alias atomic_flag_test_and_set = atomic_flag_test_and_set_impl; /// + alias atomic_flag_test_and_set_explicit = atomic_flag_test_and_set_explicit_impl; /// + alias atomic_thread_fence = atomic_thread_fence_impl; /// + alias atomic_store = atomic_store_impl; /// + alias atomic_store_explicit = atomic_store_explicit_impl; /// + alias atomic_load = atomic_load_impl; /// + alias atomic_load_explicit = atomic_load_explicit_impl; /// + alias atomic_exchange = atomic_exchange_impl; /// + alias atomic_exchange_explicit = atomic_exchange_explicit_impl; /// + alias atomic_compare_exchange_strong = atomic_compare_exchange_strong_impl; /// + alias atomic_compare_exchange_weak = atomic_compare_exchange_weak_impl; /// + alias atomic_compare_exchange_strong_explicit = atomic_compare_exchange_strong_explicit_impl; /// + alias atomic_compare_exchange_weak_explicit = atomic_compare_exchange_weak_explicit_impl; /// + alias atomic_fetch_add = atomic_fetch_add_impl; /// + alias atomic_fetch_add_explicit = atomic_fetch_add_explicit_impl; /// + alias atomic_fetch_sub = atomic_fetch_sub_impl; /// + alias atomic_fetch_sub_explicit = atomic_fetch_sub_explicit_impl; /// + alias atomic_fetch_or = atomic_fetch_or_impl; /// + alias atomic_fetch_or_explicit = atomic_fetch_or_explicit_impl; /// + alias atomic_fetch_xor = atomic_fetch_xor_impl; /// + alias atomic_fetch_xor_explicit = atomic_fetch_xor_explicit_impl; /// + alias atomic_fetch_and = atomic_fetch_and_impl; /// + alias atomic_fetch_and_explicit = atomic_fetch_and_explicit_impl; /// + } +} +else version(GNU) +{ + alias atomic_flag_clear = atomic_flag_clear_impl; /// + alias atomic_flag_clear_explicit = atomic_flag_clear_explicit_impl; /// + alias atomic_flag_test_and_set = atomic_flag_test_and_set_impl; /// + alias atomic_flag_test_and_set_explicit = atomic_flag_test_and_set_explicit_impl; /// + alias atomic_signal_fence = atomic_signal_fence_impl; /// + alias atomic_thread_fence = atomic_thread_fence_impl; /// + alias atomic_store = atomic_store_impl; /// + alias atomic_store_explicit = atomic_store_explicit_impl; /// + alias atomic_load = atomic_load_impl; /// + alias atomic_load_explicit = atomic_load_explicit_impl; /// + alias atomic_exchange = atomic_exchange_impl; /// + alias atomic_exchange_explicit = atomic_exchange_explicit_impl; /// + alias atomic_compare_exchange_strong = atomic_compare_exchange_strong_impl; /// + alias atomic_compare_exchange_weak = atomic_compare_exchange_weak_impl; /// + alias atomic_compare_exchange_strong_explicit = atomic_compare_exchange_strong_explicit_impl; /// + alias atomic_compare_exchange_weak_explicit = atomic_compare_exchange_weak_explicit_impl; /// + alias atomic_fetch_add = atomic_fetch_add_impl; /// + alias atomic_fetch_add_explicit = atomic_fetch_add_explicit_impl; /// + alias atomic_fetch_sub = atomic_fetch_sub_impl; /// + alias atomic_fetch_sub_explicit = atomic_fetch_sub_explicit_impl; /// + alias atomic_fetch_or = atomic_fetch_or_impl; /// + alias atomic_fetch_or_explicit = atomic_fetch_or_explicit_impl; /// + alias atomic_fetch_xor = atomic_fetch_xor_impl; /// + alias atomic_fetch_xor_explicit = atomic_fetch_xor_explicit_impl; /// + alias atomic_fetch_and = atomic_fetch_and_impl; /// + alias atomic_fetch_and_explicit = atomic_fetch_and_explicit_impl; /// +} + +/// +pragma(inline, true) +bool atomic_is_lock_free(A)(const shared(A)* obj) +{ + return IsAtomicLockFree!A; +} + +/// Guaranteed to be a atomic boolean type +struct atomic_flag +{ + private bool b; +} + +/// +enum ATOMIC_FLAG_INIT = atomic_flag.init; + +/// +pragma(inline, true) +void atomic_flag_clear_impl()(atomic_flag* obj) +{ + assert(obj !is null); + + atomicStore(&obj.b, false); +} + +/// +pragma(inline, true) +void atomic_flag_clear_explicit_impl()(atomic_flag* obj, memory_order order) +{ + assert(obj !is null); + + final switch (order) + { + case memory_order.memory_order_relaxed: + atomicStore!(memory_order.memory_order_relaxed)(&obj.b, false); + break; + + case memory_order.memory_order_acquire: + // What GCC does here is generate a relaxed order (no barriers) + // we'll copy it, although the D compiler should really be helping out at compile time. + atomicStore!(memory_order.memory_order_relaxed)(&obj.b, false); + break; + + case memory_order.memory_order_release: + atomicStore!(memory_order.memory_order_release)(&obj.b, false); + break; + + case memory_order.memory_order_acq_rel: + atomicStore!(memory_order.memory_order_acq_rel)(&obj.b, false); + break; + + case memory_order.memory_order_seq_cst: + atomicStore(&obj.b, false); + break; + } +} + +/// +pragma(inline, true) +bool atomic_flag_test_and_set_impl()(atomic_flag* obj) +{ + assert(obj !is null); + return atomicExchange(&obj.b, true); +} + +/// +unittest +{ + atomic_flag flag; + assert(!atomic_flag_test_and_set_impl(&flag)); + atomic_flag_clear_impl(&flag); +} + +/// +pragma(inline, true) +bool atomic_flag_test_and_set_explicit_impl()(atomic_flag* obj, memory_order order) +{ + assert(obj !is null); + + final switch (order) + { + case memory_order.memory_order_relaxed: + return atomicExchange!(memory_order.memory_order_relaxed)(&obj.b, true); + + case memory_order.memory_order_acquire: + return atomicExchange!(memory_order.memory_order_acquire)(&obj.b, true); + + case memory_order.memory_order_release: + return atomicExchange!(memory_order.memory_order_release)(&obj.b, true); + + case memory_order.memory_order_acq_rel: + return atomicExchange!(memory_order.memory_order_acq_rel)(&obj.b, true); + + case memory_order.memory_order_seq_cst: + return atomicExchange(&obj.b, true); + } +} + +/// +unittest +{ + atomic_flag flag; + assert(!atomic_flag_test_and_set_explicit_impl(&flag, memory_order.memory_order_seq_cst)); + atomic_flag_clear_explicit_impl(&flag, memory_order.memory_order_seq_cst); +} + +/** + * Initializes an atomic variable, the destination should not have any expression associated with it prior to this call. + * + * We use an out parameter instead of a pointer for destination in an attempt to communicate to the compiler that it initializers. + */ +pragma(inline, true) +void atomic_init(A, C)(out shared(A) obj, C desired) @trusted +{ + obj = cast(shared) desired; +} + +/// +unittest +{ + shared int val; + atomic_init(val, 2); +} + +/// No-op function, doesn't apply to D +pragma(inline, true) +A kill_dependency(A)(A y) @trusted +{ + return y; +} + +/// Don't allow reordering, does not emit any instructions. +pragma(inline, true) +void atomic_signal_fence_impl()(memory_order order) +{ + final switch (order) + { + case memory_order.memory_order_relaxed: + atomicSignalFence!(memory_order.memory_order_relaxed); + break; + + case memory_order.memory_order_acquire: + atomicSignalFence!(memory_order.memory_order_acquire); + break; + + case memory_order.memory_order_release: + atomicSignalFence!(memory_order.memory_order_release); + break; + + case memory_order.memory_order_acq_rel: + atomicSignalFence!(memory_order.memory_order_acq_rel); + break; + + case memory_order.memory_order_seq_cst: + atomicSignalFence!(memory_order.memory_order_seq_cst); + break; + } +} + +/// +unittest +{ + atomic_signal_fence_impl(memory_order.memory_order_seq_cst); +} + +/// Don't allow reordering, and emit a fence instruction. +pragma(inline, true) +void atomic_thread_fence_impl()(memory_order order) +{ + final switch (order) + { + case memory_order.memory_order_relaxed: + atomicFence!(memory_order.memory_order_relaxed); + break; + + case memory_order.memory_order_acquire: + atomicFence!(memory_order.memory_order_acquire); + break; + + case memory_order.memory_order_release: + atomicFence!(memory_order.memory_order_release); + break; + + case memory_order.memory_order_acq_rel: + atomicFence!(memory_order.memory_order_acq_rel); + break; + + case memory_order.memory_order_seq_cst: + atomicFence!(memory_order.memory_order_seq_cst); + break; + } +} + +/// +unittest +{ + atomic_thread_fence_impl(memory_order.memory_order_seq_cst); +} + +/// +alias atomic_bool = shared(bool); +/// +alias atomic_char = shared(char); +/// +alias atomic_schar = shared(byte); +/// +alias atomic_uchar = shared(ubyte); +/// +alias atomic_short = shared(short); +/// +alias atomic_ushort = shared(ushort); +/// +alias atomic_int = shared(int); +/// +alias atomic_uint = shared(uint); +/// +alias atomic_long = shared(c_long); +/// +alias atomic_ulong = shared(c_ulong); +/// +alias atomic_llong = shared(long); +/// +alias atomic_ullong = shared(ulong); +/// +alias atomic_char8_t = shared(char); +/// +alias atomic_char16_t = shared(wchar); +/// +alias atomic_char32_t = shared(dchar); +/// +alias atomic_wchar_t = shared(wchar); + +/// +alias atomic_int_least8_t = shared(int_least8_t); +/// +alias atomic_uint_least8_t = shared(uint_least8_t); +/// +alias atomic_int_least16_t = shared(int_least16_t); +/// +alias atomic_uint_least16_t = shared(uint_least16_t); +/// +alias atomic_int_least32_t = shared(int_least32_t); +/// +alias atomic_uint_least32_t = shared(uint_least32_t); +/// +alias atomic_int_least64_t = shared(int_least64_t); +/// +alias atomic_uint_least64_t = shared(uint_least64_t); +/// +alias atomic_int_fast8_t = shared(int_fast8_t); +/// +alias atomic_uint_fast8_t = shared(uint_fast8_t); +/// +alias atomic_int_fast16_t = shared(int_fast16_t); +/// +alias atomic_uint_fast16_t = shared(uint_fast16_t); +/// +alias atomic_int_fast32_t = shared(int_fast32_t); +/// +alias atomic_uint_fast32_t = shared(uint_fast32_t); +/// +alias atomic_int_fast64_t = shared(int_fast64_t); +/// +alias atomic_uint_fast64_t = shared(uint_fast64_t); +/// +alias atomic_intptr_t = shared(intptr_t); +/// +alias atomic_uintptr_t = shared(uintptr_t); +/// +alias atomic_size_t = shared(size_t); +/// +alias atomic_ptrdiff_t = shared(ptrdiff_t); +/// +alias atomic_intmax_t = shared(intmax_t); +/// +alias atomic_uintmax_t = shared(uintmax_t); + +/// +pragma(inline, true) +void atomic_store_impl(A, C)(shared(A)* obj, C desired) @trusted +{ + assert(obj !is null); + atomicStore(obj, cast(A)desired); +} + +/// +unittest +{ + shared(int) obj; + atomic_store_impl(&obj, 3); +} + +/// +pragma(inline, true) +void atomic_store_explicit_impl(A, C)(shared(A)* obj, C desired, memory_order order) @trusted +{ + assert(obj !is null); + + final switch (order) + { + case memory_order.memory_order_relaxed: + atomicStore!(memory_order.memory_order_relaxed)(obj, cast(A)desired); + break; + + case memory_order.memory_order_acquire: + // What GCC does here is generate a relaxed order (no barriers) + // we'll copy it, although the D compiler should really be helping out at compile time. + atomicStore!(memory_order.memory_order_relaxed)(obj, cast(A)desired); + break; + + case memory_order.memory_order_release: + atomicStore!(memory_order.memory_order_release)(obj, cast(A)desired); + break; + + case memory_order.memory_order_acq_rel: + atomicStore!(memory_order.memory_order_acq_rel)(obj, cast(A)desired); + break; + + case memory_order.memory_order_seq_cst: + atomicStore!(memory_order.memory_order_seq_cst)(obj, cast(A)desired); + break; + } +} + +/// +unittest +{ + shared(int) obj; + atomic_store_explicit_impl(&obj, 3, memory_order.memory_order_seq_cst); +} + +/// +pragma(inline, true) +A atomic_load_impl(A)(const shared(A)* obj) @trusted +{ + assert(obj !is null); + return atomicLoad(cast(shared(A)*)obj); +} + +/// +unittest +{ + shared(int) obj = 3; + assert(atomic_load_impl(&obj) == 3); +} + +/// +pragma(inline, true) +A atomic_load_explicit_impl(A)(const shared(A)* obj, memory_order order) @trusted +{ + assert(obj !is null); + + final switch (order) + { + case memory_order.memory_order_relaxed: + return atomicLoad!(memory_order.memory_order_relaxed)(obj); + + case memory_order.memory_order_acquire: + return atomicLoad!(memory_order.memory_order_acquire)(obj); + + case memory_order.memory_order_release: + // What GCC does here is generate a relaxed order (no barriers) + // we'll copy it, although the D compiler should really be helping out at compile time. + return atomicLoad!(memory_order.memory_order_relaxed)(obj); + + case memory_order.memory_order_acq_rel: + return atomicLoad!(memory_order.memory_order_acq_rel)(obj); + + case memory_order.memory_order_seq_cst: + return atomicLoad!(memory_order.memory_order_seq_cst)(obj); + } +} + +/// +unittest +{ + shared(int) obj = 3; + assert(atomic_load_explicit_impl(&obj, memory_order.memory_order_seq_cst) == 3); +} + +/// +pragma(inline, true) +A atomic_exchange_impl(A, C)(const shared(A)* obj, C desired) @trusted +{ + assert(obj !is null); + return atomicExchange(cast(shared(A)*)obj, cast(A)desired); +} + +/// +unittest +{ + shared(int) obj = 3; + assert(atomic_exchange_impl(&obj, 2) == 3); +} + +/// +pragma(inline, true) +A atomic_exchange_explicit_impl(A, C)(const shared(A)* obj, C desired, memory_order order) @trusted +{ + assert(obj !is null); + + final switch (order) + { + case memory_order.memory_order_relaxed: + return atomicExchange!(memory_order.memory_order_relaxed)(obj, cast(A)desired); + + case memory_order.memory_order_acquire: + return atomicExchange!(memory_order.memory_order_acquire)(obj, cast(A)desired); + + case memory_order.memory_order_release: + return atomicExchange!(memory_order.memory_order_release)(obj, cast(A)desired); + + case memory_order.memory_order_acq_rel: + return atomicExchange!(memory_order.memory_order_acq_rel)(obj, cast(A)desired); + + case memory_order.memory_order_seq_cst: + return atomicExchange!(memory_order.memory_order_seq_cst)(obj, cast(A)desired); + } +} + +/// +unittest +{ + shared(int) obj = 3; + assert(atomic_exchange_explicit_impl(&obj, 2, memory_order.memory_order_seq_cst) == 3); +} + +/// +pragma(inline, true) +bool atomic_compare_exchange_strong_impl(A, C)(shared(A)* obj, A* expected, C desired) @trusted +{ + return atomicCompareExchangeStrong(cast(A*)obj, expected, cast(A)desired); +} + +/// +unittest +{ + shared(int) obj = 3; + int expected = 3; + assert(atomic_compare_exchange_strong_impl(&obj, &expected, 2)); +} + +/// +pragma(inline, true) +bool atomic_compare_exchange_weak_impl(A, C)(shared(A)* obj, A* expected, C desired) @trusted +{ + return atomicCompareExchangeStrong(cast(A*)obj, expected, cast(A)desired); +} + +/// +unittest +{ + shared(int) obj = 3; + int expected = 3; + static assert(__traits(compiles, {atomic_compare_exchange_weak_impl(&obj, &expected, 2);})); +} + +/// +pragma(inline, true) +bool atomic_compare_exchange_strong_explicit_impl(A, C)(shared(A)* obj, A* expected, C desired, memory_order succ, memory_order fail) @trusted +{ + assert(obj !is null); + // We use these giant switch inside switch statements + // because as of 2023 they are capable of being for the most part inlined by gdc & ldc when using literal arguments for memory_order. + + final switch(succ) + { + case memory_order.memory_order_relaxed: + final switch(fail) + { + case memory_order.memory_order_relaxed: + return atomicCompareExchangeStrong!(memory_order.memory_order_relaxed, memory_order.memory_order_relaxed)(cast(A*)obj, expected, cast(A)desired); + case memory_order.memory_order_acquire: + return atomicCompareExchangeStrong!(memory_order.memory_order_relaxed, memory_order.memory_order_acquire)(cast(A*)obj, expected, cast(A)desired); + case memory_order.memory_order_release: + return atomicCompareExchangeStrong!(memory_order.memory_order_relaxed, memory_order.memory_order_release)(cast(A*)obj, expected, cast(A)desired); + case memory_order.memory_order_acq_rel: + return atomicCompareExchangeStrong!(memory_order.memory_order_relaxed, memory_order.memory_order_acq_rel)(cast(A*)obj, expected, cast(A)desired); + case memory_order.memory_order_seq_cst: + return atomicCompareExchangeStrong!(memory_order.memory_order_relaxed, memory_order.memory_order_seq_cst)(cast(A*)obj, expected, cast(A)desired); + } + case memory_order.memory_order_acquire: + final switch(fail) + { + case memory_order.memory_order_relaxed: + return atomicCompareExchangeStrong!(memory_order.memory_order_acquire, memory_order.memory_order_relaxed)(cast(A*)obj, expected, cast(A)desired); + case memory_order.memory_order_acquire: + return atomicCompareExchangeStrong!(memory_order.memory_order_acquire, memory_order.memory_order_acquire)(cast(A*)obj, expected, cast(A)desired); + case memory_order.memory_order_release: + return atomicCompareExchangeStrong!(memory_order.memory_order_acquire, memory_order.memory_order_release)(cast(A*)obj, expected, cast(A)desired); + case memory_order.memory_order_acq_rel: + return atomicCompareExchangeStrong!(memory_order.memory_order_acquire, memory_order.memory_order_acq_rel)(cast(A*)obj, expected, cast(A)desired); + case memory_order.memory_order_seq_cst: + return atomicCompareExchangeStrong!(memory_order.memory_order_acquire, memory_order.memory_order_seq_cst)(cast(A*)obj, expected, cast(A)desired); + } + case memory_order.memory_order_release: + final switch(fail) + { + case memory_order.memory_order_relaxed: + return atomicCompareExchangeStrong!(memory_order.memory_order_release, memory_order.memory_order_relaxed)(cast(A*)obj, expected, cast(A)desired); + case memory_order.memory_order_acquire: + return atomicCompareExchangeStrong!(memory_order.memory_order_release, memory_order.memory_order_acquire)(cast(A*)obj, expected, cast(A)desired); + case memory_order.memory_order_release: + return atomicCompareExchangeStrong!(memory_order.memory_order_release, memory_order.memory_order_release)(cast(A*)obj, expected, cast(A)desired); + case memory_order.memory_order_acq_rel: + return atomicCompareExchangeStrong!(memory_order.memory_order_release, memory_order.memory_order_acq_rel)(cast(A*)obj, expected, cast(A)desired); + case memory_order.memory_order_seq_cst: + return atomicCompareExchangeStrong!(memory_order.memory_order_release, memory_order.memory_order_seq_cst)(cast(A*)obj, expected, cast(A)desired); + } + case memory_order.memory_order_acq_rel: + final switch(fail) + { + case memory_order.memory_order_relaxed: + return atomicCompareExchangeStrong!(memory_order.memory_order_acq_rel, memory_order.memory_order_relaxed)(cast(A*)obj, expected, cast(A)desired); + case memory_order.memory_order_acquire: + return atomicCompareExchangeStrong!(memory_order.memory_order_acq_rel, memory_order.memory_order_acquire)(cast(A*)obj, expected, cast(A)desired); + case memory_order.memory_order_release: + return atomicCompareExchangeStrong!(memory_order.memory_order_acq_rel, memory_order.memory_order_release)(cast(A*)obj, expected, cast(A)desired); + case memory_order.memory_order_acq_rel: + return atomicCompareExchangeStrong!(memory_order.memory_order_acq_rel, memory_order.memory_order_acq_rel)(cast(A*)obj, expected, cast(A)desired); + case memory_order.memory_order_seq_cst: + return atomicCompareExchangeStrong!(memory_order.memory_order_acq_rel, memory_order.memory_order_seq_cst)(cast(A*)obj, expected, cast(A)desired); + } + case memory_order.memory_order_seq_cst: + final switch(fail) + { + case memory_order.memory_order_relaxed: + return atomicCompareExchangeStrong!(memory_order.memory_order_seq_cst, memory_order.memory_order_relaxed)(cast(A*)obj, expected, cast(A)desired); + case memory_order.memory_order_acquire: + return atomicCompareExchangeStrong!(memory_order.memory_order_seq_cst, memory_order.memory_order_acquire)(cast(A*)obj, expected, cast(A)desired); + case memory_order.memory_order_release: + return atomicCompareExchangeStrong!(memory_order.memory_order_seq_cst, memory_order.memory_order_release)(cast(A*)obj, expected, cast(A)desired); + case memory_order.memory_order_acq_rel: + return atomicCompareExchangeStrong!(memory_order.memory_order_seq_cst, memory_order.memory_order_acq_rel)(cast(A*)obj, expected, cast(A)desired); + case memory_order.memory_order_seq_cst: + return atomicCompareExchangeStrong!(memory_order.memory_order_seq_cst, memory_order.memory_order_seq_cst)(cast(A*)obj, expected, cast(A)desired); + } + } +} + +/// +unittest +{ + shared(int) obj = 3; + int expected = 3; + assert(atomic_compare_exchange_strong_explicit_impl(&obj, &expected, 2, memory_order.memory_order_seq_cst, memory_order.memory_order_seq_cst)); +} + +/// +pragma(inline, true) +bool atomic_compare_exchange_weak_explicit_impl(A, C)(shared(A)* obj, A* expected, C desired, memory_order succ, memory_order fail) @trusted +{ + assert(obj !is null); + // We use these giant switch inside switch statements + // because as of 2023 they are capable of being for the most part inlined by gdc & ldc when using literal arguments for memory_order. + + final switch(succ) + { + case memory_order.memory_order_relaxed: + final switch(fail) + { + case memory_order.memory_order_relaxed: + return atomicCompareExchangeWeak!(memory_order.memory_order_relaxed, memory_order.memory_order_relaxed)(cast(A*)obj, expected, cast(A)desired); + case memory_order.memory_order_acquire: + return atomicCompareExchangeWeak!(memory_order.memory_order_relaxed, memory_order.memory_order_relaxed)(cast(A*)obj, expected, cast(A)desired); + case memory_order.memory_order_release: + return atomicCompareExchangeWeak!(memory_order.memory_order_relaxed, memory_order.memory_order_relaxed)(cast(A*)obj, expected, cast(A)desired); + case memory_order.memory_order_acq_rel: + return atomicCompareExchangeWeak!(memory_order.memory_order_relaxed, memory_order.memory_order_relaxed)(cast(A*)obj, expected, cast(A)desired); + case memory_order.memory_order_seq_cst: + return atomicCompareExchangeWeak!(memory_order.memory_order_relaxed, memory_order.memory_order_relaxed)(cast(A*)obj, expected, cast(A)desired); + } + case memory_order.memory_order_acquire: + final switch(fail) + { + case memory_order.memory_order_relaxed: + return atomicCompareExchangeWeak!(memory_order.memory_order_acquire, memory_order.memory_order_relaxed)(cast(A*)obj, expected, cast(A)desired); + case memory_order.memory_order_acquire: + return atomicCompareExchangeWeak!(memory_order.memory_order_acquire, memory_order.memory_order_acquire)(cast(A*)obj, expected, cast(A)desired); + case memory_order.memory_order_release: + return atomicCompareExchangeWeak!(memory_order.memory_order_acquire, memory_order.memory_order_release)(cast(A*)obj, expected, cast(A)desired); + case memory_order.memory_order_acq_rel: + return atomicCompareExchangeWeak!(memory_order.memory_order_acquire, memory_order.memory_order_acq_rel)(cast(A*)obj, expected, cast(A)desired); + case memory_order.memory_order_seq_cst: + return atomicCompareExchangeWeak!(memory_order.memory_order_acquire, memory_order.memory_order_seq_cst)(cast(A*)obj, expected, cast(A)desired); + } + case memory_order.memory_order_release: + final switch(fail) + { + case memory_order.memory_order_relaxed: + return atomicCompareExchangeWeak!(memory_order.memory_order_release, memory_order.memory_order_relaxed)(cast(A*)obj, expected, cast(A)desired); + case memory_order.memory_order_acquire: + return atomicCompareExchangeWeak!(memory_order.memory_order_release, memory_order.memory_order_acquire)(cast(A*)obj, expected, cast(A)desired); + case memory_order.memory_order_release: + return atomicCompareExchangeWeak!(memory_order.memory_order_release, memory_order.memory_order_release)(cast(A*)obj, expected, cast(A)desired); + case memory_order.memory_order_acq_rel: + return atomicCompareExchangeWeak!(memory_order.memory_order_release, memory_order.memory_order_acq_rel)(cast(A*)obj, expected, cast(A)desired); + case memory_order.memory_order_seq_cst: + return atomicCompareExchangeWeak!(memory_order.memory_order_release, memory_order.memory_order_seq_cst)(cast(A*)obj, expected, cast(A)desired); + } + case memory_order.memory_order_acq_rel: + final switch(fail) + { + case memory_order.memory_order_relaxed: + return atomicCompareExchangeWeak!(memory_order.memory_order_acq_rel, memory_order.memory_order_relaxed)(cast(A*)obj, expected, cast(A)desired); + case memory_order.memory_order_acquire: + return atomicCompareExchangeWeak!(memory_order.memory_order_acq_rel, memory_order.memory_order_acquire)(cast(A*)obj, expected, cast(A)desired); + case memory_order.memory_order_release: + return atomicCompareExchangeWeak!(memory_order.memory_order_acq_rel, memory_order.memory_order_release)(cast(A*)obj, expected, cast(A)desired); + case memory_order.memory_order_acq_rel: + return atomicCompareExchangeWeak!(memory_order.memory_order_acq_rel, memory_order.memory_order_acq_rel)(cast(A*)obj, expected, cast(A)desired); + case memory_order.memory_order_seq_cst: + return atomicCompareExchangeWeak!(memory_order.memory_order_acq_rel, memory_order.memory_order_seq_cst)(cast(A*)obj, expected, cast(A)desired); + } + case memory_order.memory_order_seq_cst: + final switch(fail) + { + case memory_order.memory_order_relaxed: + return atomicCompareExchangeWeak!(memory_order.memory_order_seq_cst, memory_order.memory_order_relaxed)(cast(A*)obj, expected, cast(A)desired); + case memory_order.memory_order_acquire: + return atomicCompareExchangeWeak!(memory_order.memory_order_seq_cst, memory_order.memory_order_acquire)(cast(A*)obj, expected, cast(A)desired); + case memory_order.memory_order_release: + return atomicCompareExchangeWeak!(memory_order.memory_order_seq_cst, memory_order.memory_order_release)(cast(A*)obj, expected, cast(A)desired); + case memory_order.memory_order_acq_rel: + return atomicCompareExchangeWeak!(memory_order.memory_order_seq_cst, memory_order.memory_order_acq_rel)(cast(A*)obj, expected, cast(A)desired); + case memory_order.memory_order_seq_cst: + return atomicCompareExchangeWeak!(memory_order.memory_order_seq_cst, memory_order.memory_order_seq_cst)(cast(A*)obj, expected, cast(A)desired); + } + } +} + +/// +unittest +{ + shared(int) obj = 3; + int expected = 3; + atomic_compare_exchange_weak_explicit_impl(&obj, &expected, 2, memory_order.memory_order_seq_cst, memory_order.memory_order_seq_cst); +} + +/// +pragma(inline, true) +A atomic_fetch_add_impl(A, M)(shared(A)* obj, M arg) @trusted +{ + assert(obj !is null); + return atomicFetchAdd(cast(A*)obj, arg); +} + +/// +unittest +{ + shared(int) val; + atomic_fetch_add_impl(&val, 3); + assert(atomic_load_impl(&val) == 3); +} + +pragma(inline, true) +A atomic_fetch_sub_impl(A, M)(shared(A)* obj, M arg) @trusted +{ + assert(obj !is null); + return atomicFetchSub(cast(A*)obj, arg); +} + +/// +unittest +{ + shared(int) val = 3; + atomic_fetch_sub_impl(&val, 3); + assert(atomic_load_impl(&val) == 0); +} + +/// +pragma(inline, true) +A atomic_fetch_add_explicit_impl(A, M)(shared(A)* obj, M arg, memory_order order) @trusted +{ + assert(obj !is null); + + final switch(order) + { + case memory_order.memory_order_relaxed: + return atomicFetchAdd!(memory_order.memory_order_relaxed)(cast(A*)obj, arg); + case memory_order.memory_order_acquire: + return atomicFetchAdd!(memory_order.memory_order_acquire)(cast(A*)obj, arg); + case memory_order.memory_order_release: + return atomicFetchAdd!(memory_order.memory_order_release)(cast(A*)obj, arg); + case memory_order.memory_order_acq_rel: + return atomicFetchAdd!(memory_order.memory_order_acq_rel)(cast(A*)obj, arg); + case memory_order.memory_order_seq_cst: + return atomicFetchAdd!(memory_order.memory_order_seq_cst)(cast(A*)obj, arg); + } +} + +/// +unittest +{ + shared(int) val; + atomic_fetch_add_explicit_impl(&val, 3, memory_order.memory_order_seq_cst); + assert(atomic_load_impl(&val) == 3); +} + +/// +pragma(inline, true) +A atomic_fetch_sub_explicit_impl(A, M)(shared(A)* obj, M arg, memory_order order) @trusted +{ + assert(obj !is null); + + final switch(order) + { + case memory_order.memory_order_relaxed: + return atomicFetchSub!(memory_order.memory_order_relaxed)(cast(A*)obj, arg); + case memory_order.memory_order_acquire: + return atomicFetchSub!(memory_order.memory_order_acquire)(cast(A*)obj, arg); + case memory_order.memory_order_release: + return atomicFetchSub!(memory_order.memory_order_release)(cast(A*)obj, arg); + case memory_order.memory_order_acq_rel: + return atomicFetchSub!(memory_order.memory_order_acq_rel)(cast(A*)obj, arg); + case memory_order.memory_order_seq_cst: + return atomicFetchSub!(memory_order.memory_order_seq_cst)(cast(A*)obj, arg); + } +} + +/// +unittest +{ + shared(int) val = 3; + atomic_fetch_sub_explicit_impl(&val, 3, memory_order.memory_order_seq_cst); + assert(atomic_load_impl(&val) == 0); +} + +/// +pragma(inline, true) +A atomic_fetch_or_impl(A, M)(shared(A)* obj, M arg) @trusted +{ + assert(obj !is null); + + // copied from atomicOp + + A set, get = atomicLoad(cast(A*)obj); + + do + { + set = get | arg; + } while (!atomicCompareExchangeWeak!(memory_order.memory_order_seq_cst, memory_order.memory_order_seq_cst)(cast(A*)obj, &get, cast(A)set)); + + return get; +} + +/// +unittest +{ + shared(int) val = 5; + atomic_fetch_or_impl(&val, 3); + assert(atomic_load_impl(&val) == 7); +} + +/// +pragma(inline, true) +A atomic_fetch_or_explicit_impl(A, M)(shared(A)* obj, M arg, memory_order order) @trusted +{ + assert(obj !is null); + + A set, get; + + final switch(order) + { + case memory_order.memory_order_relaxed: + get = atomicLoad!(memory_order.memory_order_relaxed)(cast(A*)obj); + do + { + set = get | arg; + } while (!atomicCompareExchangeWeak!(memory_order.memory_order_relaxed, memory_order.memory_order_relaxed)(cast(A*)obj, &get, cast(A)set)); + break; + + case memory_order.memory_order_acquire: + get = atomicLoad!(memory_order.memory_order_acquire)(cast(A*)obj); + do + { + set = get | arg; + } while (!atomicCompareExchangeWeak!(memory_order.memory_order_acquire, memory_order.memory_order_acquire)(cast(A*)obj, &get, cast(A)set)); + break; + + case memory_order.memory_order_release: + get = atomicLoad!(memory_order.memory_order_relaxed)(cast(A*)obj); + do + { + set = get | arg; + } while (!atomicCompareExchangeWeak!(memory_order.memory_order_release, memory_order.memory_order_release)(cast(A*)obj, &get, cast(A)set)); + break; + + case memory_order.memory_order_acq_rel: + get = atomicLoad!(memory_order.memory_order_acq_rel)(cast(A*)obj); + do + { + set = get | arg; + } while (!atomicCompareExchangeWeak!(memory_order.memory_order_acq_rel, memory_order.memory_order_acq_rel)(cast(A*)obj, &get, cast(A)set)); + break; + + case memory_order.memory_order_seq_cst: + get = atomicLoad!(memory_order.memory_order_relaxed)(cast(A*)obj); + do + { + set = get | arg; + } while (!atomicCompareExchangeWeak!(memory_order.memory_order_seq_cst, memory_order.memory_order_seq_cst)(cast(A*)obj, &get, cast(A)set)); + break; + } + + return get; +} + +/// +unittest +{ + shared(int) val = 5; + atomic_fetch_or_explicit_impl(&val, 3, memory_order.memory_order_seq_cst); + assert(atomic_load_impl(&val) == 7); +} + +/// +pragma(inline, true) +A atomic_fetch_xor_impl(A, M)(shared(A)* obj, M arg) @trusted +{ + assert(obj !is null); + + // copied from atomicOp + + A set, get = atomicLoad(cast(A*)obj); + + do + { + set = get ^ arg; + } while (!atomicCompareExchangeWeak!(memory_order.memory_order_seq_cst, memory_order.memory_order_seq_cst)(cast(A*)obj, &get, cast(A)set)); + + return get; +} + +/// +unittest +{ + shared(int) val = 5; + atomic_fetch_xor_impl(&val, 3); + assert(atomic_load_impl(&val) == 6); +} + +/// +pragma(inline, true) +A atomic_fetch_xor_explicit_impl(A, M)(shared(A)* obj, M arg, memory_order order) @trusted +{ + assert(obj !is null); + + A set, get; + + final switch(order) + { + case memory_order.memory_order_relaxed: + get = atomicLoad!(memory_order.memory_order_relaxed)(cast(A*)obj); + do + { + set = get ^ arg; + } while (!atomicCompareExchangeWeak!(memory_order.memory_order_relaxed, memory_order.memory_order_relaxed)(cast(A*)obj, &get, cast(A)set)); + break; + + case memory_order.memory_order_acquire: + get = atomicLoad!(memory_order.memory_order_acquire)(cast(A*)obj); + do + { + set = get ^ arg; + } while (!atomicCompareExchangeWeak!(memory_order.memory_order_acquire, memory_order.memory_order_acquire)(cast(A*)obj, &get, cast(A)set)); + break; + + case memory_order.memory_order_release: + get = atomicLoad!(memory_order.memory_order_relaxed)(cast(A*)obj); + do + { + set = get ^ arg; + } while (!atomicCompareExchangeWeak!(memory_order.memory_order_release, memory_order.memory_order_release)(cast(A*)obj, &get, cast(A)set)); + break; + + case memory_order.memory_order_acq_rel: + get = atomicLoad!(memory_order.memory_order_acq_rel)(cast(A*)obj); + do + { + set = get ^ arg; + } while (!atomicCompareExchangeWeak!(memory_order.memory_order_acq_rel, memory_order.memory_order_acq_rel)(cast(A*)obj, &get, cast(A)set)); + break; + + case memory_order.memory_order_seq_cst: + get = atomicLoad!(memory_order.memory_order_relaxed)(cast(A*)obj); + do + { + set = get ^ arg; + } while (!atomicCompareExchangeWeak!(memory_order.memory_order_seq_cst, memory_order.memory_order_seq_cst)(cast(A*)obj, &get, cast(A)set)); + break; + } + + return get; +} + +/// +unittest +{ + shared(int) val = 5; + atomic_fetch_xor_explicit_impl(&val, 3, memory_order.memory_order_seq_cst); + assert(atomic_load_impl(&val) == 6); +} + +/// +pragma(inline, true) +A atomic_fetch_and_impl(A, M)(shared(A)* obj, M arg) @trusted +{ + assert(obj !is null); + + // copied from atomicOp + + A set, get = atomicLoad(cast(A*)obj); + + do + { + set = get & arg; + } while (!atomicCompareExchangeWeak!(memory_order.memory_order_seq_cst, memory_order.memory_order_seq_cst)(cast(A*)obj, &get, cast(A)set)); + + return get; +} + +/// +unittest +{ + shared(int) val = 5; + atomic_fetch_and_impl(&val, 3); + assert(atomic_load_impl(&val) == 1); +} + +/// +pragma(inline, true) +A atomic_fetch_and_explicit_impl(A, M)(shared(A)* obj, M arg, memory_order order) @trusted +{ + assert(obj !is null); + + A set, get; + + final switch(order) + { + case memory_order.memory_order_relaxed: + get = atomicLoad!(memory_order.memory_order_relaxed)(cast(A*)obj); + do + { + set = get & arg; + } while (!atomicCompareExchangeWeak!(memory_order.memory_order_relaxed, memory_order.memory_order_relaxed)(cast(A*)obj, &get, cast(A)set)); + break; + + case memory_order.memory_order_acquire: + get = atomicLoad!(memory_order.memory_order_acquire)(cast(A*)obj); + do + { + set = get & arg; + } while (!atomicCompareExchangeWeak!(memory_order.memory_order_acquire, memory_order.memory_order_acquire)(cast(A*)obj, &get, cast(A)set)); + break; + + case memory_order.memory_order_release: + get = atomicLoad!(memory_order.memory_order_relaxed)(cast(A*)obj); + do + { + set = get & arg; + } while (!atomicCompareExchangeWeak!(memory_order.memory_order_release, memory_order.memory_order_release)(cast(A*)obj, &get, cast(A)set)); + break; + + case memory_order.memory_order_acq_rel: + get = atomicLoad!(memory_order.memory_order_acq_rel)(cast(A*)obj); + do + { + set = get & arg; + } while (!atomicCompareExchangeWeak!(memory_order.memory_order_acq_rel, memory_order.memory_order_acq_rel)(cast(A*)obj, &get, cast(A)set)); + break; + + case memory_order.memory_order_seq_cst: + get = atomicLoad!(memory_order.memory_order_relaxed)(cast(A*)obj); + do + { + set = get & arg; + } while (!atomicCompareExchangeWeak!(memory_order.memory_order_seq_cst, memory_order.memory_order_seq_cst)(cast(A*)obj, &get, cast(A)set)); + break; + } + + return get; +} + +/// +unittest +{ + shared(int) val = 5; + atomic_fetch_and_explicit_impl(&val, 3, memory_order.memory_order_seq_cst); + assert(atomic_load_impl(&val) == 1); +} From 2c1ddfed915aa752603a85d30fa60f2a62183129 Mon Sep 17 00:00:00 2001 From: "Adam D. Ruppe" Date: Fri, 8 Dec 2023 11:57:37 -0500 Subject: [PATCH 086/215] make pragma great again --- dmd/frontend.h | 4 ++-- dmd/globals.d | 2 +- tests/dmd/fail_compilation/pragmas.d | 3 +-- 3 files changed, 4 insertions(+), 5 deletions(-) diff --git a/dmd/frontend.h b/dmd/frontend.h index 1dcfbea8213..c171337d706 100644 --- a/dmd/frontend.h +++ b/dmd/frontend.h @@ -3086,7 +3086,7 @@ struct Param final cov(), covPercent(), ctfe_cov(false), - ignoreUnsupportedPragmas(), + ignoreUnsupportedPragmas(true), useModuleInfo(true), useTypeInfo(true), useExceptions(true), @@ -3146,7 +3146,7 @@ struct Param final mapfile() { } - Param(bool obj, bool multiobj = false, bool trace = false, bool tracegc = false, bool vcg_ast = false, DiagnosticReporting useDeprecated = (DiagnosticReporting)1u, bool useUnitTests = false, bool useInline = false, bool release = false, bool preservePaths = false, DiagnosticReporting warnings = (DiagnosticReporting)2u, bool cov = false, uint8_t covPercent = 0u, bool ctfe_cov = false, bool ignoreUnsupportedPragmas = false, bool useModuleInfo = true, bool useTypeInfo = true, bool useExceptions = true, bool useGC = true, bool betterC = false, bool addMain = false, bool allInst = false, bool bitfields = false, CppStdRevision cplusplus = (CppStdRevision)201103u, Help help = Help(), Verbose v = Verbose(), FeatureState useDIP25 = (FeatureState)2u, FeatureState useDIP1000 = (FeatureState)0u, bool ehnogc = false, bool useDIP1021 = false, FeatureState fieldwise = (FeatureState)0u, bool fixAliasThis = false, FeatureState rvalueRefParam = (FeatureState)0u, FeatureState noSharedAccess = (FeatureState)0u, bool previewIn = false, bool inclusiveInContracts = false, bool shortenedMethods = true, bool fixImmutableConv = false, bool fix16997 = true, FeatureState dtorFields = (FeatureState)0u, FeatureState systemVariables = (FeatureState)0u, CHECKENABLE useInvariants = (CHECKENABLE)0u, CHECKENABLE useIn = (CHECKENABLE)0u, CHECKENABLE useOut = (CHECKENABLE)0u, CHECKENABLE useArrayBounds = (CHECKENABLE)0u, CHECKENABLE useAssert = (CHECKENABLE)0u, CHECKENABLE useSwitchError = (CHECKENABLE)0u, CHECKENABLE boundscheck = (CHECKENABLE)0u, CHECKACTION checkAction = (CHECKACTION)0u, _d_dynamicArray< const char > argv0 = {}, Array modFileAliasStrings = Array(), Array* imppath = nullptr, Array* fileImppath = nullptr, _d_dynamicArray< const char > objdir = {}, _d_dynamicArray< const char > objname = {}, _d_dynamicArray< const char > libname = {}, Output ddoc = Output(), Output dihdr = Output(), Output cxxhdr = Output(), Output json = Output(), JsonFieldFlags jsonFieldFlags = (JsonFieldFlags)0u, Output makeDeps = Output(), Output mixinOut = Output(), Output moduleDeps = Output(), uint32_t debuglevel = 0u, uint32_t versionlevel = 0u, bool run = false, Array runargs = Array(), Array cppswitches = Array(), const char* cpp = nullptr, Array objfiles = Array(), Array linkswitches = Array(), Array linkswitchIsForCC = Array(), Array libfiles = Array(), Array dllfiles = Array(), _d_dynamicArray< const char > deffile = {}, _d_dynamicArray< const char > resfile = {}, _d_dynamicArray< const char > exefile = {}, _d_dynamicArray< const char > mapfile = {}) : + Param(bool obj, bool multiobj = false, bool trace = false, bool tracegc = false, bool vcg_ast = false, DiagnosticReporting useDeprecated = (DiagnosticReporting)1u, bool useUnitTests = false, bool useInline = false, bool release = false, bool preservePaths = false, DiagnosticReporting warnings = (DiagnosticReporting)2u, bool cov = false, uint8_t covPercent = 0u, bool ctfe_cov = false, bool ignoreUnsupportedPragmas = true, bool useModuleInfo = true, bool useTypeInfo = true, bool useExceptions = true, bool useGC = true, bool betterC = false, bool addMain = false, bool allInst = false, bool bitfields = false, CppStdRevision cplusplus = (CppStdRevision)201103u, Help help = Help(), Verbose v = Verbose(), FeatureState useDIP25 = (FeatureState)2u, FeatureState useDIP1000 = (FeatureState)0u, bool ehnogc = false, bool useDIP1021 = false, FeatureState fieldwise = (FeatureState)0u, bool fixAliasThis = false, FeatureState rvalueRefParam = (FeatureState)0u, FeatureState noSharedAccess = (FeatureState)0u, bool previewIn = false, bool inclusiveInContracts = false, bool shortenedMethods = true, bool fixImmutableConv = false, bool fix16997 = true, FeatureState dtorFields = (FeatureState)0u, FeatureState systemVariables = (FeatureState)0u, CHECKENABLE useInvariants = (CHECKENABLE)0u, CHECKENABLE useIn = (CHECKENABLE)0u, CHECKENABLE useOut = (CHECKENABLE)0u, CHECKENABLE useArrayBounds = (CHECKENABLE)0u, CHECKENABLE useAssert = (CHECKENABLE)0u, CHECKENABLE useSwitchError = (CHECKENABLE)0u, CHECKENABLE boundscheck = (CHECKENABLE)0u, CHECKACTION checkAction = (CHECKACTION)0u, _d_dynamicArray< const char > argv0 = {}, Array modFileAliasStrings = Array(), Array* imppath = nullptr, Array* fileImppath = nullptr, _d_dynamicArray< const char > objdir = {}, _d_dynamicArray< const char > objname = {}, _d_dynamicArray< const char > libname = {}, Output ddoc = Output(), Output dihdr = Output(), Output cxxhdr = Output(), Output json = Output(), JsonFieldFlags jsonFieldFlags = (JsonFieldFlags)0u, Output makeDeps = Output(), Output mixinOut = Output(), Output moduleDeps = Output(), uint32_t debuglevel = 0u, uint32_t versionlevel = 0u, bool run = false, Array runargs = Array(), Array cppswitches = Array(), const char* cpp = nullptr, Array objfiles = Array(), Array linkswitches = Array(), Array linkswitchIsForCC = Array(), Array libfiles = Array(), Array dllfiles = Array(), _d_dynamicArray< const char > deffile = {}, _d_dynamicArray< const char > resfile = {}, _d_dynamicArray< const char > exefile = {}, _d_dynamicArray< const char > mapfile = {}) : obj(obj), multiobj(multiobj), trace(trace), diff --git a/dmd/globals.d b/dmd/globals.d index 8d88207a566..9257bc464f4 100644 --- a/dmd/globals.d +++ b/dmd/globals.d @@ -167,7 +167,7 @@ extern (C++) struct Param bool cov; // generate code coverage data ubyte covPercent; // 0..100 code coverage percentage required bool ctfe_cov = false; // generate coverage data for ctfe - bool ignoreUnsupportedPragmas; // rather than error on them + bool ignoreUnsupportedPragmas = true; // rather than error on them bool useModuleInfo = true; // generate runtime module information bool useTypeInfo = true; // generate runtime type information bool useExceptions = true; // support exception handling diff --git a/tests/dmd/fail_compilation/pragmas.d b/tests/dmd/fail_compilation/pragmas.d index 5a4b5d95d07..d967ab5451b 100644 --- a/tests/dmd/fail_compilation/pragmas.d +++ b/tests/dmd/fail_compilation/pragmas.d @@ -5,7 +5,6 @@ TEST_OUTPUT: --- fail_compilation/pragmas.d(103): Error: one boolean expression expected for `pragma(inline)`, not 2 fail_compilation/pragmas.d(108): Error: one boolean expression expected for `pragma(inline)`, not 2 -fail_compilation/pragmas.d(118): Error: unrecognized `pragma(unrecognized)` --- */ @@ -28,5 +27,5 @@ void test3() void test4() { - pragma(unrecognized, "string"); + pragma(unrecognized, "string"); // permitted, just ignored } From 0a369dde7c04a02a1d2913d278dd04b7b0906f6f Mon Sep 17 00:00:00 2001 From: Walter Bright Date: Fri, 8 Dec 2023 23:11:24 -0800 Subject: [PATCH 087/215] use isXXX() functions for ReturnStatement semantic --- dmd/statementsem.d | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/dmd/statementsem.d b/dmd/statementsem.d index b000f7d3191..fcc606b6dd5 100644 --- a/dmd/statementsem.d +++ b/dmd/statementsem.d @@ -2526,10 +2526,9 @@ Statement statementSemanticVisit(Statement s, Scope* sc) if (fd.fes) fd = fd.fes.func; // fd is now function enclosing foreach - TypeFunction tf = cast(TypeFunction)fd.type; - assert(tf.ty == Tfunction); + auto tf = fd.type.isTypeFunction(); - if (rs.exp && rs.exp.op == EXP.variable && (cast(VarExp)rs.exp).var == fd.vresult) + if (rs.exp && rs.exp.isVarExp() && rs.exp.isVarExp().var == fd.vresult) { // return vresult; if (sc.fes) @@ -2617,7 +2616,7 @@ Statement statementSemanticVisit(Statement s, Scope* sc) rs.exp.checkSharedAccess(sc, returnSharedRef); // for static alias this: https://issues.dlang.org/show_bug.cgi?id=17684 - if (rs.exp.op == EXP.type) + if (rs.exp.isTypeExp()) rs.exp = resolveAliasThis(sc, rs.exp); rs.exp = resolveProperties(sc, rs.exp); @@ -2633,14 +2632,14 @@ Statement statementSemanticVisit(Statement s, Scope* sc) // Extract side-effect part rs.exp = Expression.extractLast(rs.exp, e0); - if (rs.exp.op == EXP.call) + if (rs.exp.isCallExp()) rs.exp = valueNoDtor(rs.exp); /* Void-return function can have void / noreturn typed expression * on return statement. */ auto texp = rs.exp.type; - const convToVoid = texp.ty == Tvoid || texp.ty == Tnoreturn; + const convToVoid = texp.ty == Tvoid || texp.isTypeNoreturn(); if (tbret && tbret.ty == Tvoid || convToVoid) { @@ -2689,7 +2688,7 @@ Statement statementSemanticVisit(Statement s, Scope* sc) { tf.next = rs.exp.type; } - else if (tret.ty != Terror && !rs.exp.type.equals(tret)) + else if (!tret.isTypeError() && !rs.exp.type.equals(tret)) { int m1 = rs.exp.type.implicitConvTo(tret); int m2 = tret.implicitConvTo(rs.exp.type); @@ -2790,7 +2789,7 @@ Statement statementSemanticVisit(Statement s, Scope* sc) // Found an actual return value before else if (tf.next.ty != Tvoid && !resType.toBasetype().isTypeNoreturn()) { - if (tf.next.ty != Terror) + if (!tf.next.isTypeError()) { error(rs.loc, "mismatched function return type inference of `void` and `%s`", tf.next.toChars()); } @@ -2808,7 +2807,7 @@ Statement statementSemanticVisit(Statement s, Scope* sc) if (tbret.ty != Tvoid && !resType.isTypeNoreturn()) // if non-void return { - if (tbret.ty != Terror) + if (!tbret.isTypeError()) { if (e0) error(rs.loc, "expected return type of `%s`, not `%s`", tret.toChars(), resType.toChars()); @@ -2902,7 +2901,7 @@ Statement statementSemanticVisit(Statement s, Scope* sc) } if (e0) { - if (e0.op == EXP.declaration || e0.op == EXP.comma) + if (e0.isDeclarationExp() || e0.isCommaExp()) { rs.exp = Expression.combine(e0, rs.exp); } From 659db6fc0973394de2b11028eaf1be15c5ef4b04 Mon Sep 17 00:00:00 2001 From: Martin Kinkelin Date: Sat, 2 Dec 2023 21:15:46 +0100 Subject: [PATCH 088/215] Remove deprecated compiler Makefiles --- runtime/druntime/posix.mak | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/runtime/druntime/posix.mak b/runtime/druntime/posix.mak index 0735a976f7f..3a5d1b9295a 100644 --- a/runtime/druntime/posix.mak +++ b/runtime/druntime/posix.mak @@ -351,7 +351,8 @@ $(IMPDIR)/%.h : src/%.h ######################## Build DMD if non-existent ############################## $(DMD): - $(MAKE) -C $(DMD_DIR)/src -f posix.mak BUILD=$(BUILD) OS=$(OS) MODEL=$(MODEL) + $(MAKE) -C .. -f posix.mak generated/build + ../generated/build dmd BUILD=$(BUILD) OS=$(OS) MODEL=$(MODEL) ################### C/ASM Targets ############################ From a2333f84b7910a6d046d261af7065b2def47ab14 Mon Sep 17 00:00:00 2001 From: Martin Kinkelin Date: Sat, 2 Dec 2023 22:53:14 +0100 Subject: [PATCH 089/215] Remove deprecated compiler/test/Makefile --- tests/dmd/Makefile | 216 --------------------------------------------- 1 file changed, 216 deletions(-) delete mode 100644 tests/dmd/Makefile diff --git a/tests/dmd/Makefile b/tests/dmd/Makefile deleted file mode 100644 index 3a972700c52..00000000000 --- a/tests/dmd/Makefile +++ /dev/null @@ -1,216 +0,0 @@ -$(warning ===== DEPRECATION: test/Makefile is deprecated. Please use test/run.d instead.) - -ifeq (Windows_NT,$(OS)) - ifeq ($(findstring WOW64, $(shell uname)),WOW64) - OS:=windows - MODEL:=64 - else - OS:=windows - MODEL:=32 - endif -endif -ifeq (Win_32,$(OS)) - OS:=windows - MODEL:=32 -endif -ifeq (Win_32_64,$(OS)) - OS:=windows - MODEL:=64 -endif -ifeq (Win_64,$(OS)) - OS:=windows - MODEL:=64 -endif - -include ../src/osmodel.mak - -export OS -BUILD=release - -ifeq (freebsd,$(OS)) - SHELL=/usr/local/bin/bash -else ifeq (openbsd,$(OS)) - SHELL=/usr/local/bin/bash -else ifeq (netbsd,$(OS)) - SHELL=/usr/pkg/bin/bash -else ifeq (dragonflybsd,$(OS)) - SHELL=/usr/local/bin/bash -else - SHELL=/bin/bash -endif -QUIET=@ -export RESULTS_DIR=test_results -export MODEL - -ifeq ($(findstring win,$(OS)),win) - export EXE=.exe - - PIC?=0 - - DRUNTIME_PATH=..\..\druntime - PHOBOS_PATH=..\..\..\phobos - export DFLAGS=-I$(DRUNTIME_PATH)\import -I$(PHOBOS_PATH) - export LIB=$(PHOBOS_PATH) - - # auto-tester might run the testsuite with a different $(MODEL) than DMD - # has been compiled with. Hence we manually check which binary exists. - # For windows the $(OS) during build is: `windows` - ifeq (,$(wildcard ../../generated/windows/$(BUILD)/64/dmd$(EXE))) - DMD_MODEL=32 - else - DMD_MODEL=64 - endif - export DMD=../../generated/windows/$(BUILD)/$(DMD_MODEL)/dmd$(EXE) - -else - export EXE= - - # auto-tester might run the testsuite with a different $(MODEL) than DMD - # has been compiled with. Hence we manually check which binary exists. - ifeq (,$(wildcard ../../generated/$(OS)/$(BUILD)/64/dmd)) - DMD_MODEL=32 - else - DMD_MODEL=64 - endif - export DMD=../../generated/$(OS)/$(BUILD)/$(DMD_MODEL)/dmd - - # default to PIC, use PIC=1/0 to en-/disable PIC. - # Note that shared libraries and C files are always compiled with PIC. - ifeq ($(PIC),) - PIC:=1 - endif - ifeq ($(PIC),1) - export PIC_FLAG:=-fPIC - else - export PIC_FLAG:= - endif - - DRUNTIME_PATH=../../druntime - PHOBOS_PATH=../../../phobos - # link against shared libraries (defaults to true on supported platforms, can be overridden w/ make SHARED=0) - SHARED=$(if $(findstring $(OS),linux freebsd),1,) - DFLAGS=-I$(DRUNTIME_PATH)/import -I$(PHOBOS_PATH) -L-L$(PHOBOS_PATH)/generated/$(OS)/$(BUILD)/$(MODEL) - ifeq (1,$(SHARED)) - DFLAGS+=-defaultlib=libphobos2.so -L-rpath=$(PHOBOS_PATH)/generated/$(OS)/$(BUILD)/$(MODEL) - endif - export DFLAGS -endif - -# Try to find a suitable dmd if HOST_DMD is missing -ifeq ($(HOST_DMD),) - # Legacy support, some CI's use HOST_DC instead of HOST_DMD - ifneq ($(HOST_DC),) - $(warning Please use HOST_DMD instead of HOST_DC!) - HOST_DMD = $(HOST_DC) - else - HOST_DMD = dmd - endif -endif - -VERSION = $(filter v2.%, $(shell $(HOST_DMD) --version 2>/dev/null)) - -ifeq ($(VERSION),) - # dmd was not found in $PATH - USE_GENERATED=1 -endif - -ifneq ($(USE_GENERATED),) - # Use the generated dmd instead of the host compiler - HOST_DMD=$(DMD) - RUN_HOST_DMD=$(HOST_DMD) -conf= -else - RUN_HOST_DMD = $(HOST_DMD) -endif - -# Ensure valid paths on windows -export HOST_DMD:=$(subst \,/,$(HOST_DMD)) - -RUNNER:=$(RESULTS_DIR)/run$(EXE) -EXECUTE_RUNNER:=$(RUNNER) --environment - -# N determines the amount of parallel jobs, see ci/run.sh -ifneq ($(N),) - EXECUTE_RUNNER:=$(EXECUTE_RUNNER) --jobs=$N -endif - -# Workaround https://issues.dlang.org/show_bug.cgi?id=23517 -ifeq (osx,$(OS)) - export MACOSX_DEPLOYMENT_TARGET=11 -endif - -ifeq (windows,$(OS)) -all: - echo "Windows builds have been disabled" -else -all: run_tests -endif - -quick: $(RUNNER) - $(EXECUTE_RUNNER) $@ - -clean: - @echo "Removing output directory: $(RESULTS_DIR)" - $(QUIET)if [ -e $(RESULTS_DIR) ]; then rm -rf $(RESULTS_DIR); fi - @echo "Remove coverage listing files: *.lst" - $(QUIET)rm -rf *.lst - @echo "Remove trace files: trace.def, trace.log" - $(QUIET)rm -rf trace.log trace.def - -$(RESULTS_DIR)/.created: - @echo Creating output directory: $(RESULTS_DIR) - $(QUIET)if [ ! -d $(RESULTS_DIR) ]; then mkdir $(RESULTS_DIR); fi - $(QUIET)touch $(RESULTS_DIR)/.created - -run_tests: run_all_tests - -unit_tests: $(RUNNER) - @echo "Running unit tests" - $(EXECUTE_RUNNER) $@ - -run_runnable_tests: $(RUNNER) - $(EXECUTE_RUNNER) $@ - -start_runnable_tests: $(RUNNER) - @echo "Running runnable tests" - $(EXECUTE_RUNNER) run_runnable_tests - -run_runnable_cxx_tests: $(RUNNER) - $(EXECUTE_RUNNER) $@ - -start_runnable_cxx_tests: - @echo "Running runnable_cxx tests" - $(QUIET)$(MAKE) $(DMD_TESTSUITE_MAKE_ARGS) --no-print-directory run_runnable_cxx_tests - -run_compilable_tests: $(RUNNER) - $(EXECUTE_RUNNER) $@ - -start_compilable_tests: $(RUNNER) - @echo "Running compilable tests" - $(EXECUTE_RUNNER) run_compilable_tests - -run_fail_compilation_tests: $(RUNNER) - $(EXECUTE_RUNNER) $@ - -start_fail_compilation_tests: $(RUNNER) - @echo "Running fail compilation tests" - $(EXECUTE_RUNNER) run_fail_compilation_tests - -run_dshell_tests: $(RUNNER) - $(EXECUTE_RUNNER) $@ - -start_dshell_tests: $(RUNNER) - @echo "Running dshell tests" - $(EXECUTE_RUNNER) run_dshell_tests - -run_all_tests: $(RUNNER) - $(EXECUTE_RUNNER) - -start_all_tests: $(RUNNER) - @echo "Running all tests" - $(EXECUTE_RUNNER) all - -$(RUNNER): run.d - $(RUN_HOST_DMD) $(MODEL_FLAG) $(PIC_FLAG) -g -od$(RESULTS_DIR) -of$(RUNNER) -i -release $< - -# run.d is not reentrant because each invocation might attempt to build the required tools -.NOTPARALLEL: From 008c41045e7cb825f1fa81d95971095812f6eafd Mon Sep 17 00:00:00 2001 From: Martin Kinkelin Date: Sun, 3 Dec 2023 17:47:42 +0100 Subject: [PATCH 090/215] Convert posix.mak to generic Makefile Usable on Windows too, with a GNU make. --- dmd/osmodel.mak | 118 ++++++++++++++++++++++--------------- runtime/druntime/posix.mak | 2 +- 2 files changed, 71 insertions(+), 49 deletions(-) diff --git a/dmd/osmodel.mak b/dmd/osmodel.mak index 353ec80f2fe..3c507e43aca 100644 --- a/dmd/osmodel.mak +++ b/dmd/osmodel.mak @@ -2,44 +2,47 @@ # # Detects and sets the macros: # -# OS = one of {osx,linux,freebsd,openbsd,netbsd,dragonflybsd,solaris} +# OS = one of {windows,osx,linux,freebsd,openbsd,netbsd,dragonflybsd,solaris} # MODEL = one of { 32, 64 } # MODEL_FLAG = one of { -m32, -m64 } # ARCH = one of { x86, x86_64, aarch64 } # -# Note: -# Keep this file in sync between druntime, phobos, and dmd repositories! -# Source: https://github.com/dlang/dmd/blob/master/src/osmodel.mak +# On Windows, also sets up a bash shell. ifeq (,$(OS)) - uname_S:=$(shell uname -s) - ifeq (Darwin,$(uname_S)) - OS:=osx - endif - ifeq (Linux,$(uname_S)) - OS:=linux - endif - ifeq (FreeBSD,$(uname_S)) - OS:=freebsd - endif - ifeq (OpenBSD,$(uname_S)) - OS:=openbsd - endif - ifeq (NetBSD,$(uname_S)) - OS:=netbsd - endif - ifeq (DragonFly,$(uname_S)) - OS:=dragonflybsd - endif - ifeq (Solaris,$(uname_S)) - OS:=solaris - endif - ifeq (SunOS,$(uname_S)) - OS:=solaris - endif - ifeq (,$(OS)) - $(error Unrecognized or unsupported OS for uname: $(uname_S)) + ifneq (,$(LOCALAPPDATA)) + # assume Windows + OS:=windows + else + uname_S:=$(shell uname -s) + ifeq (Darwin,$(uname_S)) + OS:=osx + endif + ifeq (Linux,$(uname_S)) + OS:=linux + endif + ifeq (FreeBSD,$(uname_S)) + OS:=freebsd + endif + ifeq (OpenBSD,$(uname_S)) + OS:=openbsd + endif + ifeq (NetBSD,$(uname_S)) + OS:=netbsd + endif + ifeq (DragonFly,$(uname_S)) + OS:=dragonflybsd + endif + ifeq (Solaris,$(uname_S)) + OS:=solaris + endif + ifeq (SunOS,$(uname_S)) + OS:=solaris + endif + ifeq (,$(OS)) + $(error Unrecognized or unsupported OS for uname: $(uname_S)) + endif endif endif @@ -49,26 +52,45 @@ ifeq (MACOS,$(OS)) OS:=osx endif +# Windows predefines OS to e.g. `Windows_NT` +ifneq (,$(findstring Win,$(OS))) + OS:=windows +endif + +# set up bash shell on Windows +ifeq (windows,$(OS)) + # Note: setting SHELL to an absolute path to bash.exe does NOT suffice. + # The GNU tools like {rm,cp,mkdir}.exe need to be in PATH. + export PATH:=C:\Program Files\Git\usr\bin;$(PATH) + SHELL=bash.exe + $(info Using make SHELL "$(SHELL)", should be bash.) +endif + ifeq (,$(MODEL)) - ifeq ($(OS), solaris) - uname_M:=$(shell isainfo -n) - else - uname_M:=$(shell uname -m) - endif - ifneq (,$(findstring $(uname_M),x86_64 amd64)) + ifeq (windows,$(OS)) MODEL:=64 ARCH:=x86_64 - endif - ifneq (,$(findstring $(uname_M),aarch64 arm64)) - MODEL:=64 - ARCH:=aarch64 - endif - ifneq (,$(findstring $(uname_M),i386 i586 i686)) - MODEL:=32 - ARCH:=x86 - endif - ifeq (,$(MODEL)) - $(error Cannot figure 32/64 model and arch from uname -m: $(uname_M)) + else + ifeq ($(OS), solaris) + uname_M:=$(shell isainfo -n) + else + uname_M:=$(shell uname -m) + endif + ifneq (,$(findstring $(uname_M),x86_64 amd64)) + MODEL:=64 + ARCH:=x86_64 + endif + ifneq (,$(findstring $(uname_M),aarch64 arm64)) + MODEL:=64 + ARCH:=aarch64 + endif + ifneq (,$(findstring $(uname_M),i386 i586 i686)) + MODEL:=32 + ARCH:=x86 + endif + ifeq (,$(MODEL)) + $(error Cannot figure 32/64 model and arch from uname -m: $(uname_M)) + endif endif endif diff --git a/runtime/druntime/posix.mak b/runtime/druntime/posix.mak index 3a5d1b9295a..28023dadc83 100644 --- a/runtime/druntime/posix.mak +++ b/runtime/druntime/posix.mak @@ -351,7 +351,7 @@ $(IMPDIR)/%.h : src/%.h ######################## Build DMD if non-existent ############################## $(DMD): - $(MAKE) -C .. -f posix.mak generated/build + $(MAKE) -C .. generated/build DMD="" ../generated/build dmd BUILD=$(BUILD) OS=$(OS) MODEL=$(MODEL) ################### C/ASM Targets ############################ From d725e49f656e86423428c3577f0a361bafea62a7 Mon Sep 17 00:00:00 2001 From: Walter Bright Date: Mon, 11 Dec 2023 00:28:53 -0800 Subject: [PATCH 091/215] fix Issue 24274 - [REG master] ImportC: unrecognized C initializer with array in struct --- dmd/dsymbolsem.d | 2 +- dmd/initsem.d | 70 +++++++++++++++++++++++----------- tests/dmd/runnable/test24042.c | 70 +++++++++++++++++++++++++++++++++- 3 files changed, 118 insertions(+), 24 deletions(-) diff --git a/dmd/dsymbolsem.d b/dmd/dsymbolsem.d index ca6a2edad82..784df94a061 100644 --- a/dmd/dsymbolsem.d +++ b/dmd/dsymbolsem.d @@ -572,7 +572,7 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor printf(" type = %s\n", dsym.type ? dsym.type.toChars() : "null"); printf(" stc = x%llx\n", dsym.storage_class); printf(" storage_class = x%llx\n", dsym.storage_class); - printf("linkage = %d\n", dsym.linkage); + printf("linkage = %d\n", dsym._linkage); //if (strcmp(toChars(), "mul") == 0) assert(0); } //if (semanticRun > PASS.initial) diff --git a/dmd/initsem.d b/dmd/initsem.d index 0a91c393e98..1d7f56ed44a 100644 --- a/dmd/initsem.d +++ b/dmd/initsem.d @@ -803,9 +803,6 @@ extern(C++) Initializer initializerSemantic(Initializer init, Scope* sc, ref Typ Loop1: for (size_t index = 0; index < ci.initializerList.length; ) { - CInitializer cprev; - size_t indexprev; - L1: DesigInit di = ci.initializerList[index]; Designators* dlist = di.designatorList; if (dlist) @@ -833,15 +830,6 @@ extern(C++) Initializer initializerSemantic(Initializer init, Scope* sc, ref Typ continue Loop1; } } - if (cprev) - { - /* The peeling didn't work, so unpeel it - */ - ci = cprev; - index = indexprev; - di = ci.initializerList[index]; - goto L2; - } error(ci.loc, "`.%s` is not a field of `%s`\n", id.toChars(), sd.toChars()); return err(); } @@ -849,18 +837,55 @@ extern(C++) Initializer initializerSemantic(Initializer init, Scope* sc, ref Typ { if (fieldi == nfields) break; - if (index + 1 == ci.initializerList.length && di.initializer.isCInitializer()) + + auto ix = di.initializer; + + /* If a C initializer is wrapped in a C initializer, with no designators, + * peel off the outer one + */ + if (ix.isCInitializer()) { - /* Try peeling off this set of { } and see if it works + CInitializer cix = ix.isCInitializer(); + if (cix.initializerList.length == 1) + { + DesigInit dix = cix.initializerList[0]; + if (!dix.designatorList) + { + Initializer inix = dix.initializer; + if (inix.isCInitializer()) + ix = inix; + } + } + } + + if (auto cix = ix.isCInitializer()) + { + /* ImportC loses the structure from anonymous structs, but this is retained + * by the initializer syntax. if a CInitializer has a Designator, it is probably + * a nested anonymous struct */ - cprev = ci; - ci = di.initializer.isCInitializer(); - indexprev = index; - index = 0; - goto L1; + if (cix.initializerList.length) + { + DesigInit dix = cix.initializerList[0]; + Designators* dlistx = dix.designatorList; + if (dlistx && (*dlistx).length == 1 && (*dlistx)[0].ident) + { + auto id = (*dlistx)[0].ident; + foreach (k, f; sd.fields[]) // linear search for now + { + if (f.ident == id) + { + fieldi = k; + si.addInit(id, dix.initializer); + ++fieldi; + ++index; + continue Loop1; + } + } + } + } } - L2: VarDeclaration field; while (1) // skip field if it overlaps with previously seen fields { @@ -871,10 +896,11 @@ extern(C++) Initializer initializerSemantic(Initializer init, Scope* sc, ref Typ if (fieldi == nfields) break; } + auto tn = field.type.toBasetype(); auto tnsa = tn.isTypeSArray(); auto tns = tn.isTypeStruct(); - auto ix = di.initializer; + if (tnsa && ix.isExpInitializer()) { ExpInitializer ei = ix.isExpInitializer(); @@ -1013,7 +1039,7 @@ extern(C++) Initializer initializerSemantic(Initializer init, Scope* sc, ref Typ } else { - error(ci.loc, "unrecognized C initializer `%s`", toChars(ci)); + error(ci.loc, "unrecognized C initializer `%s` for type `%s`", toChars(ci), t.toChars()); return err(); } } diff --git a/tests/dmd/runnable/test24042.c b/tests/dmd/runnable/test24042.c index c2db46b19d2..c6cde72c53d 100644 --- a/tests/dmd/runnable/test24042.c +++ b/tests/dmd/runnable/test24042.c @@ -55,10 +55,75 @@ struct S3 void test3() { - struct S3 tn = (struct S3) {{0}, 4}; + struct S3 tn = (struct S3) {{1}, 4}; + assert(tn.context[0] == 1); + assert(tn.context[1] == 0); + assert(tn.context[2] == 0); + assert(tn.context[3] == 0); assert(tn.id == 4); } +/**************************************/ +// https://issues.dlang.org/show_bug.cgi?id=24274 + +struct S0 +{ + struct + { + char short_data[24]; + }; + int length; +}; + +void test4() +{ + struct S0 s0 = { {.short_data = {1}}, .length = 2}; + assert(s0.short_data[0] == 1); + assert(s0.length == 2); +} + +/**************************************/ + +struct S1 +{ + struct + { + int long_data; + char short_data[24]; + }; + int length; +}; + +void test5() +{ + struct S1 s1 = { {.short_data = {7}}, .length = 8}; + assert(s1.long_data == 0); + assert(s1.short_data[0] == 7); + assert(s1.length == 8); +} + +/**************************************/ + +struct S6 +{ + int abc[4]; +}; + +void test6() +{ + struct S6 s = {{4},5,6,7}; + assert(s.abc[0] == 4); + assert(s.abc[1] == 0); + assert(s.abc[2] == 0); + assert(s.abc[3] == 0); + + struct S6 t = {4,{5},6,7}; + assert(t.abc[0] == 4); + assert(t.abc[1] == 5); + assert(t.abc[2] == 6); + assert(t.abc[3] == 7); +} + /**************************************/ int main() @@ -66,5 +131,8 @@ int main() test1(); test2(); test3(); + test4(); + test5(); + test6(); return 0; } From 58a7de1566906b303c1bd4933b6ce7e1f120228f Mon Sep 17 00:00:00 2001 From: Martin Kinkelin Date: Tue, 12 Dec 2023 00:57:55 +0100 Subject: [PATCH 092/215] Top-level Makefile: Extract {dmd,druntime}[-test] targets For convenience, and to make the compiler build triggered from druntime/posix.mak more robust. --- runtime/druntime/posix.mak | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/runtime/druntime/posix.mak b/runtime/druntime/posix.mak index 28023dadc83..b98173dc30f 100644 --- a/runtime/druntime/posix.mak +++ b/runtime/druntime/posix.mak @@ -350,9 +350,8 @@ $(IMPDIR)/%.h : src/%.h ######################## Build DMD if non-existent ############################## -$(DMD): - $(MAKE) -C .. generated/build DMD="" - ../generated/build dmd BUILD=$(BUILD) OS=$(OS) MODEL=$(MODEL) +$(DMD_DIR)/../generated/$(OS)/$(BUILD)/$(MODEL)/dmd: + $(MAKE) -C $(DMD_DIR)/.. dmd BUILD=$(BUILD) OS=$(OS) MODEL=$(MODEL) DMD="" ################### C/ASM Targets ############################ From 475efd9e05d2d53b1316437a937c37fe11ecb627 Mon Sep 17 00:00:00 2001 From: Walter Bright Date: Mon, 11 Dec 2023 22:55:26 -0800 Subject: [PATCH 093/215] fix Issue 24276 - ImportC: typedef aliases not emitted correctly in .di files --- dmd/cparse.d | 7 ++++++- tests/dmd/compilable/ctod.i | 13 +++++++++++++ 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/dmd/cparse.d b/dmd/cparse.d index 3a39cedc4c2..6c55eee115c 100644 --- a/dmd/cparse.d +++ b/dmd/cparse.d @@ -1899,6 +1899,7 @@ final class CParser(AST) : Parser!AST } bool isalias = true; + Identifier idt; if (auto ts = dt.isTypeStruct()) { if (ts.sym.isAnonymous()) @@ -1908,6 +1909,7 @@ final class CParser(AST) : Parser!AST ts.sym.ident = id; isalias = false; } + idt = ts.sym.ident; } else if (auto te = dt.isTypeEnum()) { @@ -1917,6 +1919,7 @@ final class CParser(AST) : Parser!AST te.sym.ident = id; isalias = false; } + idt = te.sym.ident; } else if (auto tt = dt.isTypeTag()) { @@ -1930,11 +1933,13 @@ final class CParser(AST) : Parser!AST Specifier spec; declareTag(tt, spec); } + idt = tt.id; } if (isalias) { auto ad = new AST.AliasDeclaration(token.loc, id, dt); - ad.adFlags |= ad.hidden; // do not print when generating .di files + if (id == idt) + ad.adFlags |= ad.hidden; // do not print when generating .di files s = ad; } diff --git a/tests/dmd/compilable/ctod.i b/tests/dmd/compilable/ctod.i index 090f680a68a..94116aba475 100644 --- a/tests/dmd/compilable/ctod.i +++ b/tests/dmd/compilable/ctod.i @@ -22,6 +22,11 @@ extern (C) int x = void; } Foo abc(); + union S + { + int x = void; + } + alias T = S; /+enum int __DATE__ = 1+/; /+enum int __TIME__ = 1+/; /+enum int __TIMESTAMP__ = 1+/; @@ -49,6 +54,14 @@ struct Foo { struct Foo abc(void); +// https://issues.dlang.org/show_bug.cgi?id=24276 + +union S +{ + int x; +}; +typedef S T; + // https://issues.dlang.org/show_bug.cgi?id=24200 #define __DATE__ 1 From 6f3499ef4cffca1836c7f4d2ccabec7a65f48e46 Mon Sep 17 00:00:00 2001 From: Denis Feklushkin Date: Wed, 13 Dec 2023 17:48:23 +0700 Subject: [PATCH 094/215] druntime docs generator: replaces src/* by import/* (dlang/dmd!15880) * druntime docs generator: replace src/* by import/* * import/ -> src/ for rt.* modules --------- Co-authored-by: Denis Feklushkin --- runtime/druntime/posix.mak | 126 +++++++++++++++++++------------------ 1 file changed, 64 insertions(+), 62 deletions(-) diff --git a/runtime/druntime/posix.mak b/runtime/druntime/posix.mak index 0735a976f7f..6ff345339ae 100644 --- a/runtime/druntime/posix.mak +++ b/runtime/druntime/posix.mak @@ -62,7 +62,7 @@ LINKDL=$(if $(findstring $(OS),linux),-L-ldl,) MAKEFILE = $(firstword $(MAKEFILE_LIST)) -DDOCFLAGS=-conf= -c -w -o- -Isrc -Iimport -version=CoreDdoc +DDOCFLAGS=-conf= -c -w -o- -Iimport -version=CoreDdoc # Set CFLAGS CFLAGS=$(MODEL_FLAG) -fPIC -DHAVE_UNISTD_H @@ -143,188 +143,190 @@ endif doc: $(DOCS) -$(DOC_OUTPUT_DIR)/%.html : src/%.d $(DMD) +$(DOC_OUTPUT_DIR)/%.html : import/%.d $(DMD) $(DMD) $(DDOCFLAGS) -Df$@ project.ddoc $(DOCFMT) $< -$(DOC_OUTPUT_DIR)/core_%.html : src/core/%.d $(DMD) +$(DOC_OUTPUT_DIR)/core_%.html : import/core/%.d $(DMD) $(DMD) $(DDOCFLAGS) -Df$@ project.ddoc $(DOCFMT) $< -$(DOC_OUTPUT_DIR)/core_experimental_%.html : src/core/experimental/%.d $(DMD) +$(DOC_OUTPUT_DIR)/core_experimental_%.html : import/core/experimental/%.d $(DMD) $(DMD) $(DDOCFLAGS) -Df$@ project.ddoc $(DOCFMT) $< -$(DOC_OUTPUT_DIR)/core_gc_%.html : src/core/gc/%.d $(DMD) +$(DOC_OUTPUT_DIR)/core_gc_%.html : import/core/gc/%.d $(DMD) $(DMD) $(DDOCFLAGS) -Df$@ project.ddoc $(DOCFMT) $< -$(DOC_OUTPUT_DIR)/core_internal_%.html : src/core/internal/%.d $(DMD) +$(DOC_OUTPUT_DIR)/core_internal_%.html : import/core/internal/%.d $(DMD) $(DMD) $(DDOCFLAGS) -Df$@ project.ddoc $(DOCFMT) $< -$(DOC_OUTPUT_DIR)/core_internal_array_%.html : src/core/internal/array/%.d $(DMD) +$(DOC_OUTPUT_DIR)/core_internal_array_%.html : import/core/internal/array/%.d $(DMD) $(DMD) $(DDOCFLAGS) -Df$@ project.ddoc $(DOCFMT) $< -$(DOC_OUTPUT_DIR)/core_internal_backtrace_%.html : src/core/internal/backtrace/%.d $(DMD) +$(DOC_OUTPUT_DIR)/core_internal_backtrace_%.html : import/core/internal/backtrace/%.d $(DMD) $(DMD) $(DDOCFLAGS) -Df$@ project.ddoc $(DOCFMT) $< -$(DOC_OUTPUT_DIR)/core_internal_container_%.html : src/core/internal/container/%.d $(DMD) +$(DOC_OUTPUT_DIR)/core_internal_container_%.html : import/core/internal/container/%.d $(DMD) $(DMD) $(DDOCFLAGS) -Df$@ project.ddoc $(DOCFMT) $< -$(DOC_OUTPUT_DIR)/core_internal_elf_%.html : src/core/internal/elf/%.d $(DMD) +$(DOC_OUTPUT_DIR)/core_internal_elf_%.html : import/core/internal/elf/%.d $(DMD) $(DMD) $(DDOCFLAGS) -Df$@ project.ddoc $(DOCFMT) $< -$(DOC_OUTPUT_DIR)/core_internal_gc_%.html : src/core/internal/gc/%.d $(DMD) +$(DOC_OUTPUT_DIR)/core_internal_gc_%.html : import/core/internal/gc/%.d $(DMD) $(DMD) $(DDOCFLAGS) -Df$@ project.ddoc $(DOCFMT) $< -$(DOC_OUTPUT_DIR)/core_internal_gc_impl_%.html : src/core/internal/gc/impl/%.d $(DMD) +$(DOC_OUTPUT_DIR)/core_internal_gc_impl_%.html : import/core/internal/gc/impl/%.d $(DMD) $(DMD) $(DDOCFLAGS) -Df$@ project.ddoc $(DOCFMT) $< -$(DOC_OUTPUT_DIR)/core_internal_gc_impl_conservative_%.html : src/core/internal/gc/impl/conservative/%.d $(DMD) +$(DOC_OUTPUT_DIR)/core_internal_gc_impl_conservative_%.html : import/core/internal/gc/impl/conservative/%.d $(DMD) $(DMD) $(DDOCFLAGS) -Df$@ project.ddoc $(DOCFMT) $< -$(DOC_OUTPUT_DIR)/core_internal_gc_impl_manual_%.html : src/core/internal/gc/impl/manual/%.d $(DMD) +$(DOC_OUTPUT_DIR)/core_internal_gc_impl_manual_%.html : import/core/internal/gc/impl/manual/%.d $(DMD) $(DMD) $(DDOCFLAGS) -Df$@ project.ddoc $(DOCFMT) $< -$(DOC_OUTPUT_DIR)/core_internal_gc_impl_proto_%.html : src/core/internal/gc/impl/proto/%.d $(DMD) +$(DOC_OUTPUT_DIR)/core_internal_gc_impl_proto_%.html : import/core/internal/gc/impl/proto/%.d $(DMD) $(DMD) $(DDOCFLAGS) -Df$@ project.ddoc $(DOCFMT) $< -$(DOC_OUTPUT_DIR)/core_internal_util_%.html : src/core/internal/util/%.d $(DMD) +$(DOC_OUTPUT_DIR)/core_internal_util_%.html : import/core/internal/util/%.d $(DMD) $(DMD) $(DDOCFLAGS) -Df$@ project.ddoc $(DOCFMT) $< -$(DOC_OUTPUT_DIR)/core_internal_vararg_%.html : src/core/internal/vararg/%.d $(DMD) +$(DOC_OUTPUT_DIR)/core_internal_vararg_%.html : import/core/internal/vararg/%.d $(DMD) $(DMD) $(DDOCFLAGS) -Df$@ project.ddoc $(DOCFMT) $< -$(DOC_OUTPUT_DIR)/core_stdc_%.html : src/core/stdc/%.d $(DMD) +$(DOC_OUTPUT_DIR)/core_stdc_%.html : import/core/stdc/%.d $(DMD) $(DMD) $(DDOCFLAGS) -Df$@ project.ddoc $(DOCFMT) $< -$(DOC_OUTPUT_DIR)/core_stdcpp_%.html : src/core/stdcpp/%.d $(DMD) +$(DOC_OUTPUT_DIR)/core_stdcpp_%.html : import/core/stdcpp/%.d $(DMD) $(DMD) $(DDOCFLAGS) -Df$@ project.ddoc $(DOCFMT) $< -$(DOC_OUTPUT_DIR)/core_sync.html : src/core/sync/package.d $(DMD) +$(DOC_OUTPUT_DIR)/core_sync.html : import/core/sync/package.d $(DMD) $(DMD) $(DDOCFLAGS) -Df$@ project.ddoc $(DOCFMT) $< -$(DOC_OUTPUT_DIR)/core_sync_%.html : src/core/sync/%.d $(DMD) +$(DOC_OUTPUT_DIR)/core_sync_%.html : import/core/sync/%.d $(DMD) $(DMD) $(DDOCFLAGS) -Df$@ project.ddoc $(DOCFMT) $< -$(DOC_OUTPUT_DIR)/core_sys_bionic_%.html : src/core/sys/bionic/%.d $(DMD) +$(DOC_OUTPUT_DIR)/core_sys_bionic_%.html : import/core/sys/bionic/%.d $(DMD) $(DMD) $(DDOCFLAGS) -Df$@ project.ddoc $(DOCFMT) $< -$(DOC_OUTPUT_DIR)/core_sys_darwin_%.html : src/core/sys/darwin/%.d $(DMD) +$(DOC_OUTPUT_DIR)/core_sys_darwin_%.html : import/core/sys/darwin/%.d $(DMD) $(DMD) $(DDOCFLAGS) -Df$@ project.ddoc $(DOCFMT) $< -$(DOC_OUTPUT_DIR)/core_sys_darwin_mach_%.html : src/core/sys/darwin/mach/%.d $(DMD) +$(DOC_OUTPUT_DIR)/core_sys_darwin_mach_%.html : import/core/sys/darwin/mach/%.d $(DMD) $(DMD) $(DDOCFLAGS) -Df$@ project.ddoc $(DOCFMT) $< -$(DOC_OUTPUT_DIR)/core_sys_darwin_netinet_%.html : src/core/sys/darwin/netinet/%.d $(DMD) +$(DOC_OUTPUT_DIR)/core_sys_darwin_netinet_%.html : import/core/sys/darwin/netinet/%.d $(DMD) $(DMD) $(DDOCFLAGS) -Df$@ project.ddoc $(DOCFMT) $< -$(DOC_OUTPUT_DIR)/core_sys_darwin_sys_%.html : src/core/sys/darwin/sys/%.d $(DMD) +$(DOC_OUTPUT_DIR)/core_sys_darwin_sys_%.html : import/core/sys/darwin/sys/%.d $(DMD) $(DMD) $(DDOCFLAGS) -Df$@ project.ddoc $(DOCFMT) $< -$(DOC_OUTPUT_DIR)/core_sys_dragonflybsd_%.html : src/core/sys/dragonflybsd/%.d $(DMD) +$(DOC_OUTPUT_DIR)/core_sys_dragonflybsd_%.html : import/core/sys/dragonflybsd/%.d $(DMD) $(DMD) $(DDOCFLAGS) -Df$@ project.ddoc $(DOCFMT) $< -$(DOC_OUTPUT_DIR)/core_sys_dragonflybsd_netinet_%.html : src/core/sys/dragonflybsd/netinet/%.d $(DMD) +$(DOC_OUTPUT_DIR)/core_sys_dragonflybsd_netinet_%.html : import/core/sys/dragonflybsd/netinet/%.d $(DMD) $(DMD) $(DDOCFLAGS) -Df$@ project.ddoc $(DOCFMT) $< -$(DOC_OUTPUT_DIR)/core_sys_dragonflybsd_sys_%.html : src/core/sys/dragonflybsd/sys/%.d $(DMD) +$(DOC_OUTPUT_DIR)/core_sys_dragonflybsd_sys_%.html : import/core/sys/dragonflybsd/sys/%.d $(DMD) $(DMD) $(DDOCFLAGS) -Df$@ project.ddoc $(DOCFMT) $< -$(DOC_OUTPUT_DIR)/core_sys_elf_%.html : src/core/sys/elf/%.d $(DMD) +$(DOC_OUTPUT_DIR)/core_sys_elf_%.html : import/core/sys/elf/%.d $(DMD) $(DMD) $(DDOCFLAGS) -Df$@ project.ddoc $(DOCFMT) $< -$(DOC_OUTPUT_DIR)/core_sys_freebsd_%.html : src/core/sys/freebsd/%.d $(DMD) +$(DOC_OUTPUT_DIR)/core_sys_freebsd_%.html : import/core/sys/freebsd/%.d $(DMD) $(DMD) $(DDOCFLAGS) -Df$@ project.ddoc $(DOCFMT) $< -$(DOC_OUTPUT_DIR)/core_sys_freebsd_netinet_%.html : src/core/sys/freebsd/netinet/%.d $(DMD) +$(DOC_OUTPUT_DIR)/core_sys_freebsd_netinet_%.html : import/core/sys/freebsd/netinet/%.d $(DMD) $(DMD) $(DDOCFLAGS) -Df$@ project.ddoc $(DOCFMT) $< -$(DOC_OUTPUT_DIR)/core_sys_freebsd_sys_%.html : src/core/sys/freebsd/sys/%.d $(DMD) +$(DOC_OUTPUT_DIR)/core_sys_freebsd_sys_%.html : import/core/sys/freebsd/sys/%.d $(DMD) $(DMD) $(DDOCFLAGS) -Df$@ project.ddoc $(DOCFMT) $< -$(DOC_OUTPUT_DIR)/core_sys_linux_%.html : src/core/sys/linux/%.d $(DMD) +$(DOC_OUTPUT_DIR)/core_sys_linux_%.html : import/core/sys/linux/%.d $(DMD) $(DMD) $(DDOCFLAGS) -Df$@ project.ddoc $(DOCFMT) $< -$(DOC_OUTPUT_DIR)/core_sys_linux_netinet_%.html : src/core/sys/linux/netinet/%.d $(DMD) +$(DOC_OUTPUT_DIR)/core_sys_linux_netinet_%.html : import/core/sys/linux/netinet/%.d $(DMD) $(DMD) $(DDOCFLAGS) -Df$@ project.ddoc $(DOCFMT) $< -$(DOC_OUTPUT_DIR)/core_sys_linux_sys_%.html : src/core/sys/linux/sys/%.d $(DMD) +$(DOC_OUTPUT_DIR)/core_sys_linux_sys_%.html : import/core/sys/linux/sys/%.d $(DMD) $(DMD) $(DDOCFLAGS) -Df$@ project.ddoc $(DOCFMT) $< -$(DOC_OUTPUT_DIR)/core_sys_netbsd_%.html : src/core/sys/netbsd/%.d $(DMD) +$(DOC_OUTPUT_DIR)/core_sys_netbsd_%.html : import/core/sys/netbsd/%.d $(DMD) $(DMD) $(DDOCFLAGS) -Df$@ project.ddoc $(DOCFMT) $< -$(DOC_OUTPUT_DIR)/core_sys_netbsd_sys_%.html : src/core/sys/netbsd/sys/%.d $(DMD) +$(DOC_OUTPUT_DIR)/core_sys_netbsd_sys_%.html : import/core/sys/netbsd/sys/%.d $(DMD) $(DMD) $(DDOCFLAGS) -Df$@ project.ddoc $(DOCFMT) $< -$(DOC_OUTPUT_DIR)/core_sys_openbsd_%.html : src/core/sys/openbsd/%.d $(DMD) +$(DOC_OUTPUT_DIR)/core_sys_openbsd_%.html : import/core/sys/openbsd/%.d $(DMD) $(DMD) $(DDOCFLAGS) -Df$@ project.ddoc $(DOCFMT) $< -$(DOC_OUTPUT_DIR)/core_sys_openbsd_sys_%.html : src/core/sys/openbsd/sys/%.d $(DMD) +$(DOC_OUTPUT_DIR)/core_sys_openbsd_sys_%.html : import/core/sys/openbsd/sys/%.d $(DMD) $(DMD) $(DDOCFLAGS) -Df$@ project.ddoc $(DOCFMT) $< -$(DOC_OUTPUT_DIR)/core_sys_posix_%.html : src/core/sys/posix/%.d $(DMD) +$(DOC_OUTPUT_DIR)/core_sys_posix_%.html : import/core/sys/posix/%.d $(DMD) $(DMD) $(DDOCFLAGS) -Df$@ project.ddoc $(DOCFMT) $< -$(DOC_OUTPUT_DIR)/core_sys_posix_arpa_%.html : src/core/sys/posix/arpa/%.d $(DMD) +$(DOC_OUTPUT_DIR)/core_sys_posix_arpa_%.html : import/core/sys/posix/arpa/%.d $(DMD) $(DMD) $(DDOCFLAGS) -Df$@ project.ddoc $(DOCFMT) $< -$(DOC_OUTPUT_DIR)/core_sys_posix_net_%.html : src/core/sys/posix/net/%.d $(DMD) +$(DOC_OUTPUT_DIR)/core_sys_posix_net_%.html : import/core/sys/posix/net/%.d $(DMD) $(DMD) $(DDOCFLAGS) -Df$@ project.ddoc $(DOCFMT) $< -$(DOC_OUTPUT_DIR)/core_sys_posix_netinet_%.html : src/core/sys/posix/netinet/%.d $(DMD) +$(DOC_OUTPUT_DIR)/core_sys_posix_netinet_%.html : import/core/sys/posix/netinet/%.d $(DMD) $(DMD) $(DDOCFLAGS) -Df$@ project.ddoc $(DOCFMT) $< -$(DOC_OUTPUT_DIR)/core_sys_posix_stdc_%.html : src/core/sys/posix/stdc/%.d $(DMD) +$(DOC_OUTPUT_DIR)/core_sys_posix_stdc_%.html : import/core/sys/posix/stdc/%.d $(DMD) $(DMD) $(DDOCFLAGS) -Df$@ project.ddoc $(DOCFMT) $< -$(DOC_OUTPUT_DIR)/core_sys_posix_sys_%.html : src/core/sys/posix/sys/%.d $(DMD) +$(DOC_OUTPUT_DIR)/core_sys_posix_sys_%.html : import/core/sys/posix/sys/%.d $(DMD) $(DMD) $(DDOCFLAGS) -Df$@ project.ddoc $(DOCFMT) $< -$(DOC_OUTPUT_DIR)/core_sys_solaris_%.html : src/core/sys/solaris/%.d $(DMD) +$(DOC_OUTPUT_DIR)/core_sys_solaris_%.html : import/core/sys/solaris/%.d $(DMD) $(DMD) $(DDOCFLAGS) -Df$@ project.ddoc $(DOCFMT) $< -$(DOC_OUTPUT_DIR)/core_sys_solaris_sys_%.html : src/core/sys/solaris/sys/%.d $(DMD) +$(DOC_OUTPUT_DIR)/core_sys_solaris_sys_%.html : import/core/sys/solaris/sys/%.d $(DMD) $(DMD) $(DDOCFLAGS) -Df$@ project.ddoc $(DOCFMT) $< -$(DOC_OUTPUT_DIR)/core_sys_windows_%.html : src/core/sys/windows/%.d $(DMD) +$(DOC_OUTPUT_DIR)/core_sys_windows_%.html : import/core/sys/windows/%.d $(DMD) $(DMD) $(DDOCFLAGS) -Df$@ project.ddoc $(DOCFMT) $< -$(DOC_OUTPUT_DIR)/core_sys_windows_stdc_%.html : src/core/sys/windows/stdc/%.d $(DMD) +$(DOC_OUTPUT_DIR)/core_sys_windows_stdc_%.html : import/core/sys/windows/stdc/%.d $(DMD) $(DMD) $(DDOCFLAGS) -Df$@ project.ddoc $(DOCFMT) $< -$(DOC_OUTPUT_DIR)/core_thread.html : src/core/thread/package.d $(DMD) +$(DOC_OUTPUT_DIR)/core_thread.html : import/core/thread/package.d $(DMD) $(DMD) $(DDOCFLAGS) -Df$@ project.ddoc $(DOCFMT) $< -$(DOC_OUTPUT_DIR)/core_thread_%.html : src/core/thread/%.d $(DMD) +$(DOC_OUTPUT_DIR)/core_thread_%.html : import/core/thread/%.d $(DMD) $(DMD) $(DDOCFLAGS) -Df$@ project.ddoc $(DOCFMT) $< -$(DOC_OUTPUT_DIR)/core_builtins.html : src/core/builtins.d $(DMD) +$(DOC_OUTPUT_DIR)/core_builtins.html : import/core/builtins.d $(DMD) $(DMD) $(DDOCFLAGS) -Df$@ project.ddoc $(DOCFMT) $< -$(DOC_OUTPUT_DIR)/etc_linux_%.html : src/etc/linux/%.d $(DMD) +$(DOC_OUTPUT_DIR)/etc_linux_%.html : import/etc/linux/%.d $(DMD) $(DMD) $(DDOCFLAGS) -Df$@ project.ddoc $(DOCFMT) $< -$(DOC_OUTPUT_DIR)/gc_%.html : src/gc/%.d $(DMD) +$(DOC_OUTPUT_DIR)/gc_%.html : import/gc/%.d $(DMD) $(DMD) $(DDOCFLAGS) -Df$@ project.ddoc $(DOCFMT) $< -$(DOC_OUTPUT_DIR)/gc_impl_%.html : src/gc/impl/%.d $(DMD) +$(DOC_OUTPUT_DIR)/gc_impl_%.html : import/gc/impl/%.d $(DMD) $(DMD) $(DDOCFLAGS) -Df$@ project.ddoc $(DOCFMT) $< -$(DOC_OUTPUT_DIR)/gc_impl_conservative_%.html : src/gc/impl/conservative/%.d $(DMD) +$(DOC_OUTPUT_DIR)/gc_impl_conservative_%.html : import/gc/impl/conservative/%.d $(DMD) $(DMD) $(DDOCFLAGS) -Df$@ project.ddoc $(DOCFMT) $< -$(DOC_OUTPUT_DIR)/gc_impl_manual_%.html : src/gc/impl/manual/%.d $(DMD) +$(DOC_OUTPUT_DIR)/gc_impl_manual_%.html : import/gc/impl/manual/%.d $(DMD) $(DMD) $(DDOCFLAGS) -Df$@ project.ddoc $(DOCFMT) $< -$(DOC_OUTPUT_DIR)/gc_impl_proto_%.html : src/gc/impl/proto/%.d $(DMD) +$(DOC_OUTPUT_DIR)/gc_impl_proto_%.html : import/gc/impl/proto/%.d $(DMD) $(DMD) $(DDOCFLAGS) -Df$@ project.ddoc $(DOCFMT) $< +# -Isrc added here because rt.* modules isn't purposed to import, +# i.e., not copied to import/ dir, but we want to generate documentation for them too $(DOC_OUTPUT_DIR)/rt_%.html : src/rt/%.d $(DMD) - $(DMD) $(DDOCFLAGS) -Df$@ project.ddoc $(DOCFMT) $< + $(DMD) $(DDOCFLAGS) -Isrc -Df$@ project.ddoc $(DOCFMT) $< $(DOC_OUTPUT_DIR)/rt_typeinfo_%.html : src/rt/typeinfo/%.d $(DMD) - $(DMD) $(DDOCFLAGS) -Df$@ project.ddoc $(DOCFMT) $< + $(DMD) $(DDOCFLAGS) -Isrc -Df$@ project.ddoc $(DOCFMT) $< $(DOC_OUTPUT_DIR)/rt_util_%.html : src/rt/util/%.d $(DMD) - $(DMD) $(DDOCFLAGS) -Df$@ project.ddoc $(DOCFMT) $< + $(DMD) $(DDOCFLAGS) -Isrc -Df$@ project.ddoc $(DOCFMT) $< ######################## Header file copy ############################## From 58dfeca628905e5629d1afebf2b2ec221f599612 Mon Sep 17 00:00:00 2001 From: Razvan Nitu Date: Wed, 13 Dec 2023 13:54:44 +0200 Subject: [PATCH 095/215] Move static method dsymbol.Dsymbol._foreach out of dsymbol (dlang/dmd!15869) --- dmd/dmodule.d | 48 +++++++++++++++++++++++++++++++++++++++++++++++- dmd/dsymbol.d | 42 ------------------------------------------ dmd/frontend.h | 1 + dmd/traits.d | 6 +++--- 4 files changed, 51 insertions(+), 46 deletions(-) diff --git a/dmd/dmodule.d b/dmd/dmodule.d index 309c2601d26..cba6400df63 100644 --- a/dmd/dmodule.d +++ b/dmd/dmodule.d @@ -1384,7 +1384,53 @@ extern (C++) void getLocalClasses(Module mod, ref ClassDeclarations aclasses) return 0; } - ScopeDsymbol._foreach(null, mod.members, &pushAddClassDg); + _foreach(null, mod.members, &pushAddClassDg); +} + + +alias ForeachDg = int delegate(size_t idx, Dsymbol s); + +/*************************************** + * Expands attribute declarations in members in depth first + * order. Calls dg(size_t symidx, Dsymbol *sym) for each + * member. + * If dg returns !=0, stops and returns that value else returns 0. + * Use this function to avoid the O(N + N^2/2) complexity of + * calculating dim and calling N times getNth. + * Returns: + * last value returned by dg() + */ +int _foreach(Scope* sc, Dsymbols* members, scope ForeachDg dg, size_t* pn = null) +{ + assert(dg); + if (!members) + return 0; + size_t n = pn ? *pn : 0; // take over index + int result = 0; + foreach (size_t i; 0 .. members.length) + { + import dmd.attrib : AttribDeclaration; + import dmd.dtemplate : TemplateMixin; + + Dsymbol s = (*members)[i]; + if (AttribDeclaration a = s.isAttribDeclaration()) + result = _foreach(sc, a.include(sc), dg, &n); + else if (TemplateMixin tm = s.isTemplateMixin()) + result = _foreach(sc, tm.members, dg, &n); + else if (s.isTemplateInstance()) + { + } + else if (s.isUnitTestDeclaration()) + { + } + else + result = dg(n++, s); + if (result) + break; + } + if (pn) + *pn = n; // update index + return result; } /** diff --git a/dmd/dsymbol.d b/dmd/dsymbol.d index 89eb9603a00..ef8de1b1f89 100644 --- a/dmd/dsymbol.d +++ b/dmd/dsymbol.d @@ -1372,48 +1372,6 @@ public: return false; } - extern (D) alias ForeachDg = int delegate(size_t idx, Dsymbol s); - - /*************************************** - * Expands attribute declarations in members in depth first - * order. Calls dg(size_t symidx, Dsymbol *sym) for each - * member. - * If dg returns !=0, stops and returns that value else returns 0. - * Use this function to avoid the O(N + N^2/2) complexity of - * calculating dim and calling N times getNth. - * Returns: - * last value returned by dg() - */ - extern (D) static int _foreach(Scope* sc, Dsymbols* members, scope ForeachDg dg, size_t* pn = null) - { - assert(dg); - if (!members) - return 0; - size_t n = pn ? *pn : 0; // take over index - int result = 0; - foreach (size_t i; 0 .. members.length) - { - Dsymbol s = (*members)[i]; - if (AttribDeclaration a = s.isAttribDeclaration()) - result = _foreach(sc, a.include(sc), dg, &n); - else if (TemplateMixin tm = s.isTemplateMixin()) - result = _foreach(sc, tm.members, dg, &n); - else if (s.isTemplateInstance()) - { - } - else if (s.isUnitTestDeclaration()) - { - } - else - result = dg(n++, s); - if (result) - break; - } - if (pn) - *pn = n; // update index - return result; - } - override final inout(ScopeDsymbol) isScopeDsymbol() inout { return this; diff --git a/dmd/frontend.h b/dmd/frontend.h index c171337d706..1891b623a78 100644 --- a/dmd/frontend.h +++ b/dmd/frontend.h @@ -4770,6 +4770,7 @@ struct ASTCodegen final using EnumDeclaration = ::EnumDeclaration; using EnumMember = ::EnumMember; using Import = ::Import; + using ForeachDg = ::ForeachDg; using Module = ::Module; using ModuleDeclaration = ::ModuleDeclaration; using Package = ::Package; diff --git a/dmd/traits.d b/dmd/traits.d index 0acadbb4604..aebc0b5512b 100644 --- a/dmd/traits.d +++ b/dmd/traits.d @@ -1665,12 +1665,12 @@ Expression semanticTraits(TraitsExp e, Scope* sc) } else if (auto ed = sm.isEnumDeclaration()) { - ScopeDsymbol._foreach(null, ed.members, &pushIdentsDg); + _foreach(null, ed.members, &pushIdentsDg); } return 0; } - ScopeDsymbol._foreach(sc, sds.members, &pushIdentsDg); + _foreach(sc, sds.members, &pushIdentsDg); auto cd = sds.isClassDeclaration(); if (cd && e.ident == Id.allMembers) { @@ -1684,7 +1684,7 @@ Expression semanticTraits(TraitsExp e, Scope* sc) { auto cb = (*cd.baseclasses)[i].sym; assert(cb); - ScopeDsymbol._foreach(null, cb.members, &pushIdentsDg); + _foreach(null, cb.members, &pushIdentsDg); if (cb.baseclasses.length) pushBaseMembersDg(cb); } From dc703cb26a636270588a94d70e9986f966021db1 Mon Sep 17 00:00:00 2001 From: Dennis Korpel Date: Fri, 8 Dec 2023 22:03:33 +0100 Subject: [PATCH 096/215] Update -ignore documentation --- dmd/cli.d | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dmd/cli.d b/dmd/cli.d index 9fb4a41c574..a88825786c8 100644 --- a/dmd/cli.d +++ b/dmd/cli.d @@ -459,7 +459,7 @@ dmd -cov -unittest myprog.d $(P Note that multiple `-i=...` options are allowed, each one adds a pattern.)}" ), Option("ignore", - "ignore unsupported pragmas" + "deprecated flag, unsupported pragmas are always ignored now" ), Option("inline", "do function inlining", From 17fa24ea173621bebd1e11c38e02d8dcbdea5844 Mon Sep 17 00:00:00 2001 From: Razvan Nitu Date: Wed, 13 Dec 2023 17:37:30 +0200 Subject: [PATCH 097/215] Extract dsymbol.Dsymbol.importAll and turn it into a visitor (dlang/dmd!15870) --- dmd/attrib.d | 23 - dmd/attrib.h | 3 - dmd/dimport.d | 42 - dmd/dmodule.d | 64 - dmd/dsymbol.d | 4 - dmd/dsymbol.h | 2 +- dmd/dsymbolsem.d | 143 + dmd/frontend.h | 12343 +++++++++++++++++++++++---------------------- dmd/import.h | 1 - dmd/module.h | 1 - 10 files changed, 6330 insertions(+), 6296 deletions(-) diff --git a/dmd/attrib.d b/dmd/attrib.d index faf04890e8e..b60fb73831b 100644 --- a/dmd/attrib.d +++ b/dmd/attrib.d @@ -123,19 +123,6 @@ extern (C++) abstract class AttribDeclaration : Dsymbol return sc; } - override void importAll(Scope* sc) - { - Dsymbols* d = include(sc); - //printf("\tAttribDeclaration::importAll '%s', d = %p\n", toChars(), d); - if (d) - { - Scope* sc2 = newScope(sc); - d.foreachDsymbol( s => s.importAll(sc2) ); - if (sc2 != sc) - sc2.pop(); - } - } - override void addComment(const(char)* comment) { //printf("AttribDeclaration::addComment %s\n", comment); @@ -943,11 +930,6 @@ extern (C++) final class StaticIfDeclaration : ConditionalDeclaration } } - override void importAll(Scope* sc) - { - // do not evaluate condition before semantic pass - } - override const(char)* kind() const { return "static if"; @@ -1057,11 +1039,6 @@ extern (C++) final class StaticForeachDeclaration : AttribDeclaration // change this to give semantics to documentation comments on static foreach declarations } - override void importAll(Scope* sc) - { - // do not evaluate aggregate before semantic pass - } - override const(char)* kind() const { return "static foreach"; diff --git a/dmd/attrib.h b/dmd/attrib.h index 98c5e521977..b7092894471 100644 --- a/dmd/attrib.h +++ b/dmd/attrib.h @@ -26,7 +26,6 @@ class AttribDeclaration : public Dsymbol virtual Dsymbols *include(Scope *sc); virtual Scope *newScope(Scope *sc); - void importAll(Scope *sc) override; void addComment(const utf8_t *comment) override; const char *kind() const override; bool oneMember(Dsymbol **ps, Identifier *ident) override; @@ -171,7 +170,6 @@ class StaticIfDeclaration final : public ConditionalDeclaration StaticIfDeclaration *syntaxCopy(Dsymbol *s) override; Dsymbols *include(Scope *sc) override; - void importAll(Scope *sc) override; StaticIfDeclaration *isStaticIfDeclaration() override { return this; } const char *kind() const override; void accept(Visitor *v) override { v->visit(this); } @@ -190,7 +188,6 @@ class StaticForeachDeclaration final : public AttribDeclaration bool oneMember(Dsymbol **ps, Identifier *ident) override; Dsymbols *include(Scope *sc) override; void addComment(const utf8_t *comment) override; - void importAll(Scope *sc) override; const char *kind() const override; void accept(Visitor *v) override { v->visit(this); } }; diff --git a/dmd/dimport.d b/dmd/dimport.d index 5c01a9f5889..51b9220c185 100644 --- a/dmd/dimport.d +++ b/dmd/dimport.d @@ -222,48 +222,6 @@ extern (C++) final class Import : Dsymbol return global.errors != errors; } - override void importAll(Scope* sc) - { - if (mod) return; // Already done - - /* - * https://issues.dlang.org/show_bug.cgi?id=15525 - * - * Loading the import has failed, - * most likely because of parsing errors. - * Therefore we cannot trust the resulting AST. - */ - if (load(sc)) - { - // https://issues.dlang.org/show_bug.cgi?id=23873 - // For imports that are not at module or function level, - // e.g. aggregate level, the import symbol is added to the - // symbol table and later semantic is performed on it. - // This leads to semantic analysis on an malformed AST - // which causes all kinds of segfaults. - // The fix is to note that the module has errors and avoid - // semantic analysis on it. - if(mod) - mod.errors = true; - return; - } - - if (!mod) return; // Failed - - if (sc.stc & STC.static_) - isstatic = true; - mod.importAll(null); - mod.checkImportDeprecation(loc, sc); - if (sc.explicitVisibility) - visibility = sc.visibility; - if (!isstatic && !aliasId && !names.length) - sc.scopesym.importScope(mod, visibility); - // Enable access to pkgs/mod as soon as posible, because compiler - // can traverse them before the import gets semantic (Issue: 21501) - if (!aliasId && !names.length) - addPackageAccess(sc.scopesym); - } - /******************************* * Mark the imported packages as accessible from the current * scope. This access check is necessary when using FQN b/c diff --git a/dmd/dmodule.d b/dmd/dmodule.d index cba6400df63..6c9e90a2c8f 100644 --- a/dmd/dmodule.d +++ b/dmd/dmodule.d @@ -921,70 +921,6 @@ extern (C++) final class Module : Package return this; } - override void importAll(Scope* prevsc) - { - //printf("+Module::importAll(this = %p, '%s'): parent = %p\n", this, toChars(), parent); - if (_scope) - return; // already done - if (filetype == FileType.ddoc) - { - error(loc, "%s `%s` is a Ddoc file, cannot import it", kind, toPrettyChars); - return; - } - - /* Note that modules get their own scope, from scratch. - * This is so regardless of where in the syntax a module - * gets imported, it is unaffected by context. - * Ignore prevsc. - */ - Scope* sc = Scope.createGlobal(this, global.errorSink); // create root scope - - if (md && md.msg) - md.msg = semanticString(sc, md.msg, "deprecation message"); - - // Add import of "object", even for the "object" module. - // If it isn't there, some compiler rewrites, like - // classinst == classinst -> .object.opEquals(classinst, classinst) - // would fail inside object.d. - if (filetype != FileType.c && - (members.length == 0 || - (*members)[0].ident != Id.object || - (*members)[0].isImport() is null)) - { - auto im = new Import(Loc.initial, null, Id.object, null, 0); - members.shift(im); - } - if (!symtab) - { - // Add all symbols into module's symbol table - symtab = new DsymbolTable(); - for (size_t i = 0; i < members.length; i++) - { - Dsymbol s = (*members)[i]; - s.addMember(sc, sc.scopesym); - } - } - // anything else should be run after addMember, so version/debug symbols are defined - /* Set scope for the symbols so that if we forward reference - * a symbol, it can possibly be resolved on the spot. - * If this works out well, it can be extended to all modules - * before any semantic() on any of them. - */ - this.setScope(sc); // remember module scope for semantic - for (size_t i = 0; i < members.length; i++) - { - Dsymbol s = (*members)[i]; - s.setScope(sc); - } - for (size_t i = 0; i < members.length; i++) - { - Dsymbol s = (*members)[i]; - s.importAll(sc); - } - sc = sc.pop(); - sc.pop(); // 2 pops because Scope.createGlobal() created 2 - } - /********************************** * Determine if we need to generate an instance of ModuleInfo * for this Module. diff --git a/dmd/dsymbol.d b/dmd/dsymbol.d index ef8de1b1f89..05fcce5aa08 100644 --- a/dmd/dsymbol.d +++ b/dmd/dsymbol.d @@ -713,10 +713,6 @@ extern (C++) class Dsymbol : ASTNode return toAlias(); } - void importAll(Scope* sc) - { - } - bool overloadInsert(Dsymbol s) { //printf("Dsymbol::overloadInsert('%s')\n", s.toChars()); diff --git a/dmd/dsymbol.h b/dmd/dsymbol.h index 589d00033fc..b20d0aedbd3 100644 --- a/dmd/dsymbol.h +++ b/dmd/dsymbol.h @@ -228,7 +228,6 @@ class Dsymbol : public ASTNode virtual const char *kind() const; virtual Dsymbol *toAlias(); // resolve real symbol virtual Dsymbol *toAlias2(); - virtual void importAll(Scope *sc); virtual bool overloadInsert(Dsymbol *s); virtual uinteger_t size(const Loc &loc); virtual bool isforwardRef(); @@ -431,3 +430,4 @@ void addMember(Dsymbol *dsym, Scope *sc, ScopeDsymbol *sds); Dsymbol *search(Dsymbol *d, const Loc &loc, Identifier *ident, SearchOptFlags flags = (SearchOptFlags)SearchOpt::localsOnly); bool checkDeprecated(Dsymbol *d, const Loc &loc, Scope *sc); void setScope(Dsymbol *d, Scope *sc); +void importAll(Dsymbol *d, Scope *sc); diff --git a/dmd/dsymbolsem.d b/dmd/dsymbolsem.d index 784df94a061..ce4856c4f3b 100644 --- a/dmd/dsymbolsem.d +++ b/dmd/dsymbolsem.d @@ -8745,3 +8745,146 @@ private extern(C++) class SetScopeVisitor : Visitor visit(cast(AttribDeclaration)uad); } } + +extern(C++) void importAll(Dsymbol d, Scope* sc) +{ + scope iav = new ImportAllVisitor(sc); + d.accept(iav); +} + +extern(C++) class ImportAllVisitor : Visitor +{ + alias visit = typeof(super).visit; + Scope* sc; + + this(Scope* sc) + { + this.sc = sc; + } + + override void visit(Dsymbol d) {} + + override void visit(Import imp) + { + if (imp.mod) return; // Already done + + /* + * https://issues.dlang.org/show_bug.cgi?id=15525 + * + * Loading the import has failed, + * most likely because of parsing errors. + * Therefore we cannot trust the resulting AST. + */ + if (imp.load(sc)) + { + // https://issues.dlang.org/show_bug.cgi?id=23873 + // For imports that are not at module or function level, + // e.g. aggregate level, the import symbol is added to the + // symbol table and later semantic is performed on it. + // This leads to semantic analysis on an malformed AST + // which causes all kinds of segfaults. + // The fix is to note that the module has errors and avoid + // semantic analysis on it. + if(imp.mod) + imp.mod.errors = true; + return; + } + + if (!imp.mod) return; // Failed + + if (sc.stc & STC.static_) + imp.isstatic = true; + imp.mod.importAll(null); + imp.mod.checkImportDeprecation(imp.loc, sc); + if (sc.explicitVisibility) + imp.visibility = sc.visibility; + if (!imp.isstatic && !imp.aliasId && !imp.names.length) + sc.scopesym.importScope(imp.mod, imp.visibility); + // Enable access to pkgs/mod as soon as posible, because compiler + // can traverse them before the import gets semantic (Issue: 21501) + if (!imp.aliasId && !imp.names.length) + imp.addPackageAccess(sc.scopesym); + } + + override void visit(Module m) + { + //printf("+Module::importAll(this = %p, '%s'): parent = %p\n", m, m.toChars(), m.parent); + if (m._scope) + return; // already done + if (m.filetype == FileType.ddoc) + { + error(m.loc, "%s `%s` is a Ddoc file, cannot import it", m.kind, m.toPrettyChars); + return; + } + + /* Note that modules get their own scope, from scratch. + * This is so regardless of where in the syntax a module + * gets imported, it is unaffected by context. + * Ignore prevsc. + */ + Scope* sc = Scope.createGlobal(m, global.errorSink); // create root scope + + if (m.md && m.md.msg) + m.md.msg = semanticString(sc, m.md.msg, "deprecation message"); + + // Add import of "object", even for the "object" module. + // If it isn't there, some compiler rewrites, like + // classinst == classinst -> .object.opEquals(classinst, classinst) + // would fail inside object.d. + if (m.filetype != FileType.c && + (m.members.length == 0 || + (*m.members)[0].ident != Id.object || + (*m.members)[0].isImport() is null)) + { + auto im = new Import(Loc.initial, null, Id.object, null, 0); + m.members.shift(im); + } + if (!m.symtab) + { + // Add all symbols into module's symbol table + m.symtab = new DsymbolTable(); + for (size_t i = 0; i < m.members.length; i++) + { + Dsymbol s = (*m.members)[i]; + s.addMember(sc, sc.scopesym); + } + } + // anything else should be run after addMember, so version/debug symbols are defined + /* Set scope for the symbols so that if we forward reference + * a symbol, it can possibly be resolved on the spot. + * If this works out well, it can be extended to all modules + * before any semantic() on any of them. + */ + m.setScope(sc); // remember module scope for semantic + for (size_t i = 0; i < m.members.length; i++) + { + Dsymbol s = (*m.members)[i]; + s.setScope(sc); + } + for (size_t i = 0; i < m.members.length; i++) + { + Dsymbol s = (*m.members)[i]; + s.importAll(sc); + } + sc = sc.pop(); + sc.pop(); // 2 pops because Scope.createGlobal() created 2 + } + + override void visit(AttribDeclaration atb) + { + Dsymbols* d = atb.include(sc); + //printf("\tAttribDeclaration::importAll '%s', d = %p\n", toChars(), d); + if (d) + { + Scope* sc2 = atb.newScope(sc); + d.foreachDsymbol( s => s.importAll(sc2) ); + if (sc2 != sc) + sc2.pop(); + } + } + + // do not evaluate condition before semantic pass + override void visit(StaticIfDeclaration _) {} + // do not evaluate aggregate before semantic pass + override void visit(StaticForeachDeclaration _) {} +} diff --git a/dmd/frontend.h b/dmd/frontend.h index 1891b623a78..3a81a867252 100644 --- a/dmd/frontend.h +++ b/dmd/frontend.h @@ -133,10 +133,22 @@ class ScopeGuardStatement; struct DocComment; class WithStatement; struct AA; -class Tuple; +class CaseStatement; +class Catch; +struct Designator; +class GotoCaseStatement; +class GotoStatement; class Parameter; +class ReturnStatement; +class ScopeStatement; class TemplateParameter; +class TemplateTypeParameter; +class TemplateValueParameter; +class TemplateAliasParameter; +class TemplateThisParameter; +class TemplateTupleParameter; struct TemplatePrevious; +class TypeQualified; struct TYPE; class TypeBasic; class TypeFunction; @@ -161,12 +173,6 @@ class TypeMixin; class TypeTraits; class TypeNoreturn; class TypeTag; -class TemplateTypeParameter; -class TemplateValueParameter; -class TemplateAliasParameter; -class TemplateThisParameter; -class TemplateTupleParameter; -class TypeQualified; class StringExp; class IntegerExp; class ErrorExp; @@ -281,13 +287,6 @@ class ThrownExceptionExp; class UnaExp; class BinExp; class BinAssignExp; -class CaseStatement; -class Catch; -struct Designator; -class GotoCaseStatement; -class GotoStatement; -class ReturnStatement; -class ScopeStatement; struct ContractInfo; struct ObjcSelector; class PeelStatement; @@ -498,7 +497,6 @@ class Dsymbol : public ASTNode virtual const char* kind() const; virtual Dsymbol* toAlias(); virtual Dsymbol* toAlias2(); - virtual void importAll(Scope* sc); virtual bool overloadInsert(Dsymbol* s); virtual uinteger_t size(const Loc& loc); virtual bool isforwardRef(); @@ -959,7013 +957,7044 @@ struct AssocArray final } }; -enum class TY : uint8_t -{ - Tarray = 0u, - Tsarray = 1u, - Taarray = 2u, - Tpointer = 3u, - Treference = 4u, - Tfunction = 5u, - Tident = 6u, - Tclass = 7u, - Tstruct = 8u, - Tenum = 9u, - Tdelegate = 10u, - Tnone = 11u, - Tvoid = 12u, - Tint8 = 13u, - Tuns8 = 14u, - Tint16 = 15u, - Tuns16 = 16u, - Tint32 = 17u, - Tuns32 = 18u, - Tint64 = 19u, - Tuns64 = 20u, - Tfloat32 = 21u, - Tfloat64 = 22u, - Tfloat80 = 23u, - Timaginary32 = 24u, - Timaginary64 = 25u, - Timaginary80 = 26u, - Tcomplex32 = 27u, - Tcomplex64 = 28u, - Tcomplex80 = 29u, - Tbool = 30u, - Tchar = 31u, - Twchar = 32u, - Tdchar = 33u, - Terror = 34u, - Tinstance = 35u, - Ttypeof = 36u, - Ttuple = 37u, - Tslice = 38u, - Treturn = 39u, - Tnull = 40u, - Tvector = 41u, - Tint128 = 42u, - Tuns128 = 43u, - Ttraits = 44u, - Tmixin = 45u, - Tnoreturn = 46u, - Ttag = 47u, -}; - -enum class Covariant -{ - distinct = 0, - yes = 1, - no = 2, - fwdref = 3, -}; - -typedef uint64_t dinteger_t; - -class Type : public ASTNode +template +class ParseTimeVisitor { public: - TY ty; - uint8_t mod; - char* deco; - struct Mcache final - { - Type* cto; - Type* ito; - Type* sto; - Type* scto; - Type* wto; - Type* wcto; - Type* swto; - Type* swcto; - Mcache() : - cto(), - ito(), - sto(), - scto(), - wto(), - wcto(), - swto(), - swcto() - { - } - Mcache(Type* cto, Type* ito = nullptr, Type* sto = nullptr, Type* scto = nullptr, Type* wto = nullptr, Type* wcto = nullptr, Type* swto = nullptr, Type* swcto = nullptr) : - cto(cto), - ito(ito), - sto(sto), - scto(scto), - wto(wto), - wcto(wcto), - swto(swto), - swcto(swcto) - {} - }; - -private: - Mcache* mcache; -public: - Type* pto; - Type* rto; - Type* arrayof; - TypeInfoDeclaration* vtinfo; - TYPE* ctype; - static Type* tvoid; - static Type* tint8; - static Type* tuns8; - static Type* tint16; - static Type* tuns16; - static Type* tint32; - static Type* tuns32; - static Type* tint64; - static Type* tuns64; - static Type* tint128; - static Type* tuns128; - static Type* tfloat32; - static Type* tfloat64; - static Type* tfloat80; - static Type* timaginary32; - static Type* timaginary64; - static Type* timaginary80; - static Type* tcomplex32; - static Type* tcomplex64; - static Type* tcomplex80; - static Type* tbool; - static Type* tchar; - static Type* twchar; - static Type* tdchar; - static Type* tshiftcnt; - static Type* tvoidptr; - static Type* tstring; - static Type* twstring; - static Type* tdstring; - static Type* terror; - static Type* tnull; - static Type* tnoreturn; - static Type* tsize_t; - static Type* tptrdiff_t; - static Type* thash_t; - static ClassDeclaration* dtypeinfo; - static ClassDeclaration* typeinfoclass; - static ClassDeclaration* typeinfointerface; - static ClassDeclaration* typeinfostruct; - static ClassDeclaration* typeinfopointer; - static ClassDeclaration* typeinfoarray; - static ClassDeclaration* typeinfostaticarray; - static ClassDeclaration* typeinfoassociativearray; - static ClassDeclaration* typeinfovector; - static ClassDeclaration* typeinfoenum; - static ClassDeclaration* typeinfofunction; - static ClassDeclaration* typeinfodelegate; - static ClassDeclaration* typeinfotypelist; - static ClassDeclaration* typeinfoconst; - static ClassDeclaration* typeinfoinvariant; - static ClassDeclaration* typeinfoshared; - static ClassDeclaration* typeinfowild; - static TemplateDeclaration* rtinfo; - static Type* basic[48LLU]; - virtual const char* kind() const; - Type* copy() const; - virtual Type* syntaxCopy(); - bool equals(const RootObject* const o) const override; - bool equivalent(Type* t); - DYNCAST dyncast() const final override; - size_t getUniqueID() const; - Covariant covariant(Type* t, uint64_t* pstc = nullptr, bool cppCovariant = false); - const char* toChars() const final override; - char* toPrettyChars(bool QualifyTypes = false); - static void _init(); - static void deinitialize(); - uinteger_t size(); - virtual uinteger_t size(const Loc& loc); - virtual uint32_t alignsize(); - Type* trySemantic(const Loc& loc, Scope* sc); - Type* merge2(); - void modToBuffer(OutBuffer& buf) const; - char* modToChars() const; - virtual bool isintegral(); - virtual bool isfloating(); - virtual bool isreal(); - virtual bool isimaginary(); - virtual bool iscomplex(); - virtual bool isscalar(); - virtual bool isunsigned(); - virtual bool isscope(); - virtual bool isString(); - virtual bool isAssignable(); - virtual bool isBoolean(); - virtual void checkDeprecated(const Loc& loc, Scope* sc); - bool isConst() const; - bool isImmutable() const; - bool isMutable() const; - bool isShared() const; - bool isSharedConst() const; - bool isWild() const; - bool isWildConst() const; - bool isSharedWild() const; - bool isNaked() const; - Type* nullAttributes() const; - Type* constOf(); - Type* immutableOf(); - Type* mutableOf(); - Type* sharedOf(); - Type* sharedConstOf(); - Type* unSharedOf(); - Type* wildOf(); - Type* wildConstOf(); - Type* sharedWildOf(); - Type* sharedWildConstOf(); - Type* castMod(uint8_t mod); - Type* addMod(uint8_t mod); - virtual Type* addStorageClass(StorageClass stc); - Type* pointerTo(); - Type* referenceTo(); - Type* arrayOf(); - Type* sarrayOf(dinteger_t dim); - bool hasDeprecatedAliasThis(); - Type* aliasthisOf(); - virtual Type* makeConst(); - virtual Type* makeImmutable(); - virtual Type* makeShared(); - virtual Type* makeSharedConst(); - virtual Type* makeWild(); - virtual Type* makeWildConst(); - virtual Type* makeSharedWild(); - virtual Type* makeSharedWildConst(); - virtual Type* makeMutable(); - virtual Dsymbol* toDsymbol(Scope* sc); - Type* toBasetype(); - virtual bool isBaseOf(Type* t, int32_t* poffset); - virtual MATCH implicitConvTo(Type* to); - virtual MATCH constConv(Type* to); - virtual uint8_t deduceWild(Type* t, bool isRef); - virtual Type* substWildTo(uint32_t mod); - Type* unqualify(uint32_t m); - virtual Type* toHeadMutable(); - virtual ClassDeclaration* isClassHandle(); - virtual structalign_t alignment(); - virtual Expression* defaultInitLiteral(const Loc& loc); - virtual bool isZeroInit(const Loc& loc); - Identifier* getTypeInfoIdent(); - virtual int32_t hasWild() const; - virtual bool hasPointers(); - virtual bool hasVoidInitPointers(); - virtual bool hasSystemFields(); - virtual bool hasInvariant(); - virtual Type* nextOf(); - Type* baseElemOf(); - uint32_t numberOfElems(const Loc& loc); - virtual bool needsDestruction(); - virtual bool needsCopyOrPostblit(); - virtual bool needsNested(); - virtual TypeBasic* isTypeBasic(); - TypeFunction* isPtrToFunction(); - TypeFunction* isFunction_Delegate_PtrToFunction(); - TypeError* isTypeError(); - TypeVector* isTypeVector(); - TypeSArray* isTypeSArray(); - TypeDArray* isTypeDArray(); - TypeAArray* isTypeAArray(); - TypePointer* isTypePointer(); - TypeReference* isTypeReference(); - TypeFunction* isTypeFunction(); - TypeDelegate* isTypeDelegate(); - TypeIdentifier* isTypeIdentifier(); - TypeInstance* isTypeInstance(); - TypeTypeof* isTypeTypeof(); - TypeReturn* isTypeReturn(); - TypeStruct* isTypeStruct(); - TypeEnum* isTypeEnum(); - TypeClass* isTypeClass(); - TypeTuple* isTypeTuple(); - TypeSlice* isTypeSlice(); - TypeNull* isTypeNull(); - TypeMixin* isTypeMixin(); - TypeTraits* isTypeTraits(); - TypeNoreturn* isTypeNoreturn(); - TypeTag* isTypeTag(); - void accept(Visitor* v) override; - TypeFunction* toTypeFunction(); -}; - -enum class EXP : uint8_t -{ - reserved = 0u, - negate = 1u, - cast_ = 2u, - null_ = 3u, - assert_ = 4u, - array = 5u, - call = 6u, - address = 7u, - type = 8u, - throw_ = 9u, - new_ = 10u, - delete_ = 11u, - star = 12u, - symbolOffset = 13u, - variable = 14u, - dotVariable = 15u, - dotIdentifier = 16u, - dotTemplateInstance = 17u, - dotType = 18u, - slice = 19u, - arrayLength = 20u, - dollar = 21u, - template_ = 22u, - dotTemplateDeclaration = 23u, - declaration = 24u, - dSymbol = 25u, - typeid_ = 26u, - uadd = 27u, - remove = 28u, - newAnonymousClass = 29u, - arrayLiteral = 30u, - assocArrayLiteral = 31u, - structLiteral = 32u, - classReference = 33u, - thrownException = 34u, - delegatePointer = 35u, - delegateFunctionPointer = 36u, - lessThan = 37u, - greaterThan = 38u, - lessOrEqual = 39u, - greaterOrEqual = 40u, - equal = 41u, - notEqual = 42u, - identity = 43u, - notIdentity = 44u, - index = 45u, - is_ = 46u, - leftShift = 47u, - rightShift = 48u, - leftShiftAssign = 49u, - rightShiftAssign = 50u, - unsignedRightShift = 51u, - unsignedRightShiftAssign = 52u, - concatenate = 53u, - concatenateAssign = 54u, - concatenateElemAssign = 55u, - concatenateDcharAssign = 56u, - add = 57u, - min = 58u, - addAssign = 59u, - minAssign = 60u, - mul = 61u, - div = 62u, - mod = 63u, - mulAssign = 64u, - divAssign = 65u, - modAssign = 66u, - and_ = 67u, - or_ = 68u, - xor_ = 69u, - andAssign = 70u, - orAssign = 71u, - xorAssign = 72u, - assign = 73u, - not_ = 74u, - tilde = 75u, - plusPlus = 76u, - minusMinus = 77u, - construct = 78u, - blit = 79u, - dot = 80u, - comma = 81u, - question = 82u, - andAnd = 83u, - orOr = 84u, - prePlusPlus = 85u, - preMinusMinus = 86u, - identifier = 87u, - string_ = 88u, - this_ = 89u, - super_ = 90u, - halt = 91u, - tuple = 92u, - error = 93u, - void_ = 94u, - int64 = 95u, - float64 = 96u, - complex80 = 97u, - import_ = 98u, - delegate_ = 99u, - function_ = 100u, - mixin_ = 101u, - in_ = 102u, - break_ = 103u, - continue_ = 104u, - goto_ = 105u, - scope_ = 106u, - traits = 107u, - overloadSet = 108u, - line = 109u, - file = 110u, - fileFullPath = 111u, - moduleString = 112u, - functionString = 113u, - prettyFunction = 114u, - pow = 115u, - powAssign = 116u, - vector = 117u, - voidExpression = 118u, - cantExpression = 119u, - showCtfeContext = 120u, - objcClassReference = 121u, - vectorArray = 122u, - compoundLiteral = 123u, - _Generic_ = 124u, - interval = 125u, - loweredAssignExp = 126u, -}; - -struct complex_t final -{ - _d_real re; - _d_real im; - complex_t() = delete; - complex_t(_d_real re); - complex_t(_d_real re, _d_real im); - int32_t opEquals(complex_t y) const; -}; - -template -struct Optional final -{ - T value; - bool present; - Optional(T value); - static Optional create(T val); - bool isPresent() const; - bool isEmpty() const; - T get(); - bool hasValue(T exp) const; - Optional() - { - } -}; - -enum class OwnedBy : uint8_t -{ - code = 0u, - ctfe = 1u, - cache = 2u, -}; - -enum class TOK : uint8_t -{ - reserved = 0u, - leftParenthesis = 1u, - rightParenthesis = 2u, - leftBracket = 3u, - rightBracket = 4u, - leftCurly = 5u, - rightCurly = 6u, - colon = 7u, - semicolon = 8u, - dotDotDot = 9u, - endOfFile = 10u, - cast_ = 11u, - null_ = 12u, - assert_ = 13u, - true_ = 14u, - false_ = 15u, - throw_ = 16u, - new_ = 17u, - delete_ = 18u, - variable = 19u, - slice = 20u, - version_ = 21u, - module_ = 22u, - dollar = 23u, - template_ = 24u, - typeof_ = 25u, - pragma_ = 26u, - typeid_ = 27u, - comment = 28u, - lessThan = 29u, - greaterThan = 30u, - lessOrEqual = 31u, - greaterOrEqual = 32u, - equal = 33u, - notEqual = 34u, - identity = 35u, - notIdentity = 36u, - is_ = 37u, - leftShift = 38u, - rightShift = 39u, - leftShiftAssign = 40u, - rightShiftAssign = 41u, - unsignedRightShift = 42u, - unsignedRightShiftAssign = 43u, - concatenateAssign = 44u, - add = 45u, - min = 46u, - addAssign = 47u, - minAssign = 48u, - mul = 49u, - div = 50u, - mod = 51u, - mulAssign = 52u, - divAssign = 53u, - modAssign = 54u, - and_ = 55u, - or_ = 56u, - xor_ = 57u, - andAssign = 58u, - orAssign = 59u, - xorAssign = 60u, - assign = 61u, - not_ = 62u, - tilde = 63u, - plusPlus = 64u, - minusMinus = 65u, - dot = 66u, - comma = 67u, - question = 68u, - andAnd = 69u, - orOr = 70u, - int32Literal = 71u, - uns32Literal = 72u, - int64Literal = 73u, - uns64Literal = 74u, - int128Literal = 75u, - uns128Literal = 76u, - float32Literal = 77u, - float64Literal = 78u, - float80Literal = 79u, - imaginary32Literal = 80u, - imaginary64Literal = 81u, - imaginary80Literal = 82u, - charLiteral = 83u, - wcharLiteral = 84u, - dcharLiteral = 85u, - identifier = 86u, - string_ = 87u, - hexadecimalString = 88u, - this_ = 89u, - super_ = 90u, - error = 91u, - void_ = 92u, - int8 = 93u, - uns8 = 94u, - int16 = 95u, - uns16 = 96u, - int32 = 97u, - uns32 = 98u, - int64 = 99u, - uns64 = 100u, - int128 = 101u, - uns128 = 102u, - float32 = 103u, - float64 = 104u, - float80 = 105u, - imaginary32 = 106u, - imaginary64 = 107u, - imaginary80 = 108u, - complex32 = 109u, - complex64 = 110u, - complex80 = 111u, - char_ = 112u, - wchar_ = 113u, - dchar_ = 114u, - bool_ = 115u, - struct_ = 116u, - class_ = 117u, - interface_ = 118u, - union_ = 119u, - enum_ = 120u, - import_ = 121u, - alias_ = 122u, - override_ = 123u, - delegate_ = 124u, - function_ = 125u, - mixin_ = 126u, - align_ = 127u, - extern_ = 128u, - private_ = 129u, - protected_ = 130u, - public_ = 131u, - export_ = 132u, - static_ = 133u, - final_ = 134u, - const_ = 135u, - abstract_ = 136u, - debug_ = 137u, - deprecated_ = 138u, - in_ = 139u, - out_ = 140u, - inout_ = 141u, - lazy_ = 142u, - auto_ = 143u, - package_ = 144u, - immutable_ = 145u, - if_ = 146u, - else_ = 147u, - while_ = 148u, - for_ = 149u, - do_ = 150u, - switch_ = 151u, - case_ = 152u, - default_ = 153u, - break_ = 154u, - continue_ = 155u, - with_ = 156u, - synchronized_ = 157u, - return_ = 158u, - goto_ = 159u, - try_ = 160u, - catch_ = 161u, - finally_ = 162u, - asm_ = 163u, - foreach_ = 164u, - foreach_reverse_ = 165u, - scope_ = 166u, - onScopeExit = 167u, - onScopeFailure = 168u, - onScopeSuccess = 169u, - invariant_ = 170u, - unittest_ = 171u, - argumentTypes = 172u, - ref_ = 173u, - macro_ = 174u, - parameters = 175u, - traits = 176u, - pure_ = 177u, - nothrow_ = 178u, - gshared = 179u, - line = 180u, - file = 181u, - fileFullPath = 182u, - moduleString = 183u, - functionString = 184u, - prettyFunction = 185u, - shared_ = 186u, - at = 187u, - pow = 188u, - powAssign = 189u, - goesTo = 190u, - vector = 191u, - pound = 192u, - arrow = 193u, - colonColon = 194u, - wchar_tLiteral = 195u, - endOfLine = 196u, - whitespace = 197u, - inline_ = 198u, - register_ = 199u, - restrict_ = 200u, - signed_ = 201u, - sizeof_ = 202u, - typedef_ = 203u, - unsigned_ = 204u, - volatile_ = 205u, - _Alignas_ = 206u, - _Alignof_ = 207u, - _Atomic_ = 208u, - _Bool_ = 209u, - _Complex_ = 210u, - _Generic_ = 211u, - _Imaginary_ = 212u, - _Noreturn_ = 213u, - _Static_assert_ = 214u, - _Thread_local_ = 215u, - _assert_ = 216u, - _import_ = 217u, - __cdecl_ = 218u, - __declspec_ = 219u, - __stdcall_ = 220u, - __thread_ = 221u, - __pragma_ = 222u, - __int128_ = 223u, - __attribute___ = 224u, -}; - -enum class MemorySet -{ - none = 0, - blockAssign = 1, - referenceInit = 2, -}; - -template -class ParseTimeVisitor -{ -public: - virtual void visit(typename AST::Dsymbol ); - virtual void visit(typename AST::Parameter ); - virtual void visit(typename AST::Statement ); - virtual void visit(typename AST::Type ); - virtual void visit(typename AST::Expression ); - virtual void visit(typename AST::TemplateParameter ); - virtual void visit(typename AST::Condition ); - virtual void visit(typename AST::Initializer ); - virtual void visit(typename AST::AliasThis s); - virtual void visit(typename AST::Declaration s); - virtual void visit(typename AST::ScopeDsymbol s); - virtual void visit(typename AST::Import s); - virtual void visit(typename AST::AttribDeclaration s); - virtual void visit(typename AST::StaticAssert s); - virtual void visit(typename AST::DebugSymbol s); - virtual void visit(typename AST::VersionSymbol s); - virtual void visit(typename AST::AliasAssign s); - virtual void visit(typename AST::Package s); - virtual void visit(typename AST::EnumDeclaration s); - virtual void visit(typename AST::AggregateDeclaration s); - virtual void visit(typename AST::TemplateDeclaration s); - virtual void visit(typename AST::TemplateInstance s); - virtual void visit(typename AST::Nspace s); - virtual void visit(typename AST::VarDeclaration s); - virtual void visit(typename AST::FuncDeclaration s); - virtual void visit(typename AST::AliasDeclaration s); - virtual void visit(typename AST::TupleDeclaration s); - virtual void visit(typename AST::FuncLiteralDeclaration s); - virtual void visit(typename AST::PostBlitDeclaration s); - virtual void visit(typename AST::CtorDeclaration s); - virtual void visit(typename AST::DtorDeclaration s); - virtual void visit(typename AST::InvariantDeclaration s); - virtual void visit(typename AST::UnitTestDeclaration s); - virtual void visit(typename AST::NewDeclaration s); - virtual void visit(typename AST::StaticCtorDeclaration s); - virtual void visit(typename AST::StaticDtorDeclaration s); - virtual void visit(typename AST::SharedStaticCtorDeclaration s); - virtual void visit(typename AST::SharedStaticDtorDeclaration s); - virtual void visit(typename AST::MixinDeclaration s); - virtual void visit(typename AST::UserAttributeDeclaration s); - virtual void visit(typename AST::LinkDeclaration s); - virtual void visit(typename AST::AnonDeclaration s); - virtual void visit(typename AST::AlignDeclaration s); - virtual void visit(typename AST::CPPMangleDeclaration s); - virtual void visit(typename AST::CPPNamespaceDeclaration s); - virtual void visit(typename AST::VisibilityDeclaration s); - virtual void visit(typename AST::PragmaDeclaration s); - virtual void visit(typename AST::StorageClassDeclaration s); - virtual void visit(typename AST::ConditionalDeclaration s); - virtual void visit(typename AST::StaticForeachDeclaration s); - virtual void visit(typename AST::DeprecatedDeclaration s); - virtual void visit(typename AST::StaticIfDeclaration s); - virtual void visit(typename AST::EnumMember s); - virtual void visit(typename AST::Module s); - virtual void visit(typename AST::StructDeclaration s); - virtual void visit(typename AST::UnionDeclaration s); - virtual void visit(typename AST::ClassDeclaration s); - virtual void visit(typename AST::InterfaceDeclaration s); - virtual void visit(typename AST::TemplateMixin s); - virtual void visit(typename AST::BitFieldDeclaration s); - virtual void visit(typename AST::ImportStatement s); - virtual void visit(typename AST::ScopeStatement s); - virtual void visit(typename AST::ReturnStatement s); - virtual void visit(typename AST::LabelStatement s); - virtual void visit(typename AST::StaticAssertStatement s); - virtual void visit(typename AST::MixinStatement s); - virtual void visit(typename AST::WhileStatement s); - virtual void visit(typename AST::ForStatement s); - virtual void visit(typename AST::DoStatement s); - virtual void visit(typename AST::ForeachRangeStatement s); - virtual void visit(typename AST::ForeachStatement s); - virtual void visit(typename AST::IfStatement s); - virtual void visit(typename AST::ScopeGuardStatement s); - virtual void visit(typename AST::ConditionalStatement s); - virtual void visit(typename AST::StaticForeachStatement s); - virtual void visit(typename AST::PragmaStatement s); - virtual void visit(typename AST::SwitchStatement s); - virtual void visit(typename AST::CaseRangeStatement s); - virtual void visit(typename AST::CaseStatement s); - virtual void visit(typename AST::DefaultStatement s); - virtual void visit(typename AST::BreakStatement s); - virtual void visit(typename AST::ContinueStatement s); - virtual void visit(typename AST::GotoDefaultStatement s); - virtual void visit(typename AST::GotoCaseStatement s); - virtual void visit(typename AST::GotoStatement s); - virtual void visit(typename AST::SynchronizedStatement s); - virtual void visit(typename AST::WithStatement s); - virtual void visit(typename AST::TryCatchStatement s); - virtual void visit(typename AST::TryFinallyStatement s); - virtual void visit(typename AST::ThrowStatement s); - virtual void visit(typename AST::AsmStatement s); - virtual void visit(typename AST::ExpStatement s); - virtual void visit(typename AST::CompoundStatement s); - virtual void visit(typename AST::CompoundDeclarationStatement s); - virtual void visit(typename AST::CompoundAsmStatement s); - virtual void visit(typename AST::InlineAsmStatement s); - virtual void visit(typename AST::GccAsmStatement s); - virtual void visit(typename AST::TypeBasic t); - virtual void visit(typename AST::TypeError t); - virtual void visit(typename AST::TypeNull t); - virtual void visit(typename AST::TypeNoreturn t); - virtual void visit(typename AST::TypeVector t); - virtual void visit(typename AST::TypeEnum t); - virtual void visit(typename AST::TypeTuple t); - virtual void visit(typename AST::TypeClass t); - virtual void visit(typename AST::TypeStruct t); - virtual void visit(typename AST::TypeNext t); - virtual void visit(typename AST::TypeQualified t); - virtual void visit(typename AST::TypeTraits t); - virtual void visit(typename AST::TypeMixin t); - virtual void visit(typename AST::TypeTag t); - virtual void visit(typename AST::TypeReference t); - virtual void visit(typename AST::TypeSlice t); - virtual void visit(typename AST::TypeDelegate t); - virtual void visit(typename AST::TypePointer t); - virtual void visit(typename AST::TypeFunction t); - virtual void visit(typename AST::TypeArray t); - virtual void visit(typename AST::TypeDArray t); - virtual void visit(typename AST::TypeAArray t); - virtual void visit(typename AST::TypeSArray t); - virtual void visit(typename AST::TypeIdentifier t); - virtual void visit(typename AST::TypeReturn t); - virtual void visit(typename AST::TypeTypeof t); - virtual void visit(typename AST::TypeInstance t); - virtual void visit(typename AST::DeclarationExp e); - virtual void visit(typename AST::IntegerExp e); - virtual void visit(typename AST::NewAnonClassExp e); - virtual void visit(typename AST::IsExp e); - virtual void visit(typename AST::RealExp e); - virtual void visit(typename AST::NullExp e); - virtual void visit(typename AST::TypeidExp e); - virtual void visit(typename AST::TraitsExp e); - virtual void visit(typename AST::StringExp e); - virtual void visit(typename AST::NewExp e); - virtual void visit(typename AST::AssocArrayLiteralExp e); - virtual void visit(typename AST::ArrayLiteralExp e); - virtual void visit(typename AST::MixinExp e); - virtual void visit(typename AST::FuncExp e); - virtual void visit(typename AST::IntervalExp e); - virtual void visit(typename AST::TypeExp e); - virtual void visit(typename AST::ScopeExp e); - virtual void visit(typename AST::IdentifierExp e); - virtual void visit(typename AST::UnaExp e); - virtual void visit(typename AST::DefaultInitExp e); - virtual void visit(typename AST::BinExp e); - virtual void visit(typename AST::DsymbolExp e); - virtual void visit(typename AST::TemplateExp e); - virtual void visit(typename AST::SymbolExp e); - virtual void visit(typename AST::TupleExp e); - virtual void visit(typename AST::ThisExp e); - virtual void visit(typename AST::GenericExp e); - virtual void visit(typename AST::VarExp e); - virtual void visit(typename AST::DollarExp e); - virtual void visit(typename AST::SuperExp e); - virtual void visit(typename AST::AddrExp e); - virtual void visit(typename AST::PreExp e); - virtual void visit(typename AST::PtrExp e); - virtual void visit(typename AST::NegExp e); - virtual void visit(typename AST::UAddExp e); - virtual void visit(typename AST::NotExp e); - virtual void visit(typename AST::ComExp e); - virtual void visit(typename AST::DeleteExp e); - virtual void visit(typename AST::CastExp e); - virtual void visit(typename AST::CallExp e); - virtual void visit(typename AST::DotIdExp e); - virtual void visit(typename AST::AssertExp e); - virtual void visit(typename AST::ThrowExp e); - virtual void visit(typename AST::ImportExp e); - virtual void visit(typename AST::DotTemplateInstanceExp e); - virtual void visit(typename AST::ArrayExp e); - virtual void visit(typename AST::FuncInitExp e); - virtual void visit(typename AST::PrettyFuncInitExp e); - virtual void visit(typename AST::FileInitExp e); - virtual void visit(typename AST::LineInitExp e); - virtual void visit(typename AST::ModuleInitExp e); - virtual void visit(typename AST::CommaExp e); - virtual void visit(typename AST::PostExp e); - virtual void visit(typename AST::PowExp e); - virtual void visit(typename AST::MulExp e); - virtual void visit(typename AST::DivExp e); - virtual void visit(typename AST::ModExp e); - virtual void visit(typename AST::AddExp e); - virtual void visit(typename AST::MinExp e); - virtual void visit(typename AST::CatExp e); - virtual void visit(typename AST::ShlExp e); - virtual void visit(typename AST::ShrExp e); - virtual void visit(typename AST::UshrExp e); - virtual void visit(typename AST::EqualExp e); - virtual void visit(typename AST::InExp e); - virtual void visit(typename AST::IdentityExp e); - virtual void visit(typename AST::CmpExp e); - virtual void visit(typename AST::AndExp e); - virtual void visit(typename AST::XorExp e); - virtual void visit(typename AST::OrExp e); - virtual void visit(typename AST::LogicalExp e); - virtual void visit(typename AST::CondExp e); - virtual void visit(typename AST::AssignExp e); - virtual void visit(typename AST::BinAssignExp e); - virtual void visit(typename AST::AddAssignExp e); - virtual void visit(typename AST::MinAssignExp e); - virtual void visit(typename AST::MulAssignExp e); - virtual void visit(typename AST::DivAssignExp e); - virtual void visit(typename AST::ModAssignExp e); - virtual void visit(typename AST::PowAssignExp e); - virtual void visit(typename AST::AndAssignExp e); - virtual void visit(typename AST::OrAssignExp e); - virtual void visit(typename AST::XorAssignExp e); - virtual void visit(typename AST::ShlAssignExp e); - virtual void visit(typename AST::ShrAssignExp e); - virtual void visit(typename AST::UshrAssignExp e); - virtual void visit(typename AST::CatAssignExp e); - virtual void visit(typename AST::CatElemAssignExp e); - virtual void visit(typename AST::CatDcharAssignExp e); - virtual void visit(typename AST::TemplateAliasParameter tp); - virtual void visit(typename AST::TemplateTypeParameter tp); - virtual void visit(typename AST::TemplateTupleParameter tp); - virtual void visit(typename AST::TemplateValueParameter tp); - virtual void visit(typename AST::TemplateThisParameter tp); - virtual void visit(typename AST::StaticIfCondition c); - virtual void visit(typename AST::DVCondition c); - virtual void visit(typename AST::DebugCondition c); - virtual void visit(typename AST::VersionCondition c); - virtual void visit(typename AST::ExpInitializer i); - virtual void visit(typename AST::StructInitializer i); - virtual void visit(typename AST::ArrayInitializer i); - virtual void visit(typename AST::VoidInitializer i); - virtual void visit(typename AST::DefaultInitializer i); - virtual void visit(typename AST::CInitializer i); -}; - -struct MangleOverride final -{ - Dsymbol* agg; - Identifier* id; - MangleOverride() : - agg(), - id() - { - } - MangleOverride(Dsymbol* agg, Identifier* id = nullptr) : - agg(agg), - id(id) - {} -}; - -typedef Array AliasDeclarations; - -typedef Array BaseClasses; - -typedef Array CaseStatements; - -typedef Array Catches; - -typedef Array ClassDeclarations; - -struct DesigInit final -{ - Array* designatorList; - Initializer* initializer; - DesigInit() : - designatorList(), - initializer() - { - } - DesigInit(Array* designatorList, Initializer* initializer = nullptr) : - designatorList(designatorList), - initializer(initializer) - {} -}; - -typedef Array DesigInits; - -struct Designator final -{ - Expression* exp; - Identifier* ident; - Designator() : - exp(), - ident() - { - } -}; - -typedef Array Designators; - -typedef Array Dsymbols; - -typedef Array DtorDeclarations; - -struct Ensure final -{ - Identifier* id; - Statement* ensure; - Ensure syntaxCopy(); - static Array* arraySyntaxCopy(Array* a); - Ensure() : - id(), - ensure() - { - } - Ensure(Identifier* id, Statement* ensure = nullptr) : - id(id), - ensure(ensure) - {} -}; - -typedef Array Ensures; - -typedef Array Expressions; - -typedef Array FuncDeclarations; - -typedef Array GotoCaseStatements; - -typedef Array GotoStatements; - -typedef Array Identifiers; - -typedef Array Initializers; - -typedef Array Modules; - -typedef Array Objects; - -typedef Array Parameters; - -typedef Array ReturnStatements; - -typedef Array ScopeStatements; - -typedef Array SharedStaticDtorDeclarations; - -typedef Array Statements; - -typedef Array StaticDtorDeclarations; - -typedef Array Strings; - -typedef Array TemplateInstances; - -typedef Array TemplateParameters; - -typedef Array Types; - -typedef Array VarDeclarations; - -enum class ClassFlags : uint32_t -{ - none = 0u, - isCOMclass = 1u, - noPointers = 2u, - hasOffTi = 4u, - hasCtor = 8u, - hasGetMembers = 16u, - hasTypeInfo = 32u, - isAbstract = 64u, - isCPPclass = 128u, - hasDtor = 256u, -}; - -struct MatchAccumulator final -{ - int32_t count; - MATCH last; - FuncDeclaration* lastf; - FuncDeclaration* nextf; - MatchAccumulator() : - count(), - last((MATCH)0), - lastf(), - nextf() - { - } - MatchAccumulator(int32_t count, MATCH last = (MATCH)0, FuncDeclaration* lastf = nullptr, FuncDeclaration* nextf = nullptr) : - count(count), - last(last), - lastf(lastf), - nextf(nextf) - {} -}; - -enum class StructFlags -{ - none = 0, - hasPointers = 1, -}; - -struct FieldState final -{ - uint32_t offset; - uint32_t fieldOffset; - uint32_t fieldSize; - uint32_t fieldAlign; - uint32_t bitOffset; - bool inFlight; - FieldState() : - offset(), - fieldOffset(), - fieldSize(), - fieldAlign(), - bitOffset(), - inFlight() - { - } - FieldState(uint32_t offset, uint32_t fieldOffset = 0u, uint32_t fieldSize = 0u, uint32_t fieldAlign = 0u, uint32_t bitOffset = 0u, bool inFlight = false) : - offset(offset), - fieldOffset(fieldOffset), - fieldSize(fieldSize), - fieldAlign(fieldAlign), - bitOffset(bitOffset), - inFlight(inFlight) - {} -}; - -enum class SearchOpt : uint32_t -{ - all = 0u, - ignorePrivateImports = 1u, - ignoreErrors = 2u, - ignoreAmbiguous = 4u, - localsOnly = 8u, - importsOnly = 16u, - unqualifiedModule = 32u, - tagNameSpace = 64u, - ignoreVisibility = 128u, -}; - -typedef uint32_t SearchOptFlags; - -enum : int32_t { IDX_NOTFOUND = 305419896 }; - -struct TemplateInstanceBox final -{ - TemplateInstance* ti; - TemplateInstanceBox() : - ti() - { - } -}; - -struct TemplatePrevious final -{ - TemplatePrevious* prev; - Scope* sc; - Array* dedargs; - TemplatePrevious() : - prev(), - sc(), - dedargs() - { - } - TemplatePrevious(TemplatePrevious* prev, Scope* sc = nullptr, Array* dedargs = nullptr) : - prev(prev), - sc(sc), - dedargs(dedargs) - {} -}; - -struct TemplateStats final -{ - uint32_t numInstantiations; - uint32_t uniqueInstantiations; - Array* allInstances; - TemplateStats() : - numInstantiations(), - uniqueInstantiations(), - allInstances() - { - } - TemplateStats(uint32_t numInstantiations, uint32_t uniqueInstantiations = 0u, Array* allInstances = nullptr) : - numInstantiations(numInstantiations), - uniqueInstantiations(uniqueInstantiations), - allInstances(allInstances) - {} -}; - -struct ArgumentList final -{ - Array* arguments; - Array* names; - ArgumentList() : - arguments(), - names() - { - } - ArgumentList(Array* arguments, Array* names = nullptr) : - arguments(arguments), - names(names) - {} -}; - -enum : bool { LOGSEMANTIC = false }; - -enum class Modifiable -{ - no = 0, - yes = 1, - initialization = 2, -}; - -enum class ModifyFlags -{ - none = 0, - noError = 1, - fieldAssign = 2, -}; - -enum : int32_t { WANTexpand = 1 }; - -enum : int32_t { WANTvalue = 0 }; - -enum : int32_t { stageApply = 8 }; - -enum : int32_t { stageInlineScan = 16 }; - -enum : int32_t { stageOptimize = 4 }; - -enum : int32_t { stageScrub = 1 }; - -enum : int32_t { stageSearchPointers = 2 }; - -enum : int32_t { stageToCBuffer = 32 }; - -struct AttributeViolation final -{ - Loc loc; - const char* fmtStr; - RootObject* arg0; - RootObject* arg1; - RootObject* arg2; - AttributeViolation() : - loc(Loc(0u, 0u, 0u)), - fmtStr(nullptr), - arg0(nullptr), - arg1(nullptr), - arg2(nullptr) - { - } - AttributeViolation(Loc loc, const char* fmtStr = nullptr, RootObject* arg0 = nullptr, RootObject* arg1 = nullptr, RootObject* arg2 = nullptr) : - loc(loc), - fmtStr(fmtStr), - arg0(arg0), - arg1(arg1), - arg2(arg2) - {} -}; - -enum class ILS : uint8_t -{ - uninitialized = 0u, - no = 1u, - yes = 2u, -}; - -enum class PINLINE : uint8_t -{ - default_ = 0u, - never = 1u, - always = 2u, -}; - -struct ObjcFuncDeclaration final -{ - ObjcSelector* selector; - VarDeclaration* selectorParameter; - bool isOptional; - ObjcFuncDeclaration() : - selector(), - selectorParameter(), - isOptional() - { - } - ObjcFuncDeclaration(ObjcSelector* selector, VarDeclaration* selectorParameter = nullptr, bool isOptional = false) : - selector(selector), - selectorParameter(selectorParameter), - isOptional(isOptional) - {} -}; - -enum class PURE : uint8_t -{ - impure = 0u, - fwdref = 1u, - weak = 2u, - const_ = 3u, -}; - -enum class VarArg : uint8_t -{ - none = 0u, - variadic = 1u, - typesafe = 2u, - KRvariadic = 3u, -}; - -struct ParameterList final -{ - Array* parameters; - StorageClass stc; - VarArg varargs; - bool hasIdentifierList; - ParameterList(Array* parameters, VarArg varargs = (VarArg)0u, StorageClass stc = 0); - size_t length(); - Parameter* opIndex(size_t i); - ParameterList() : - parameters(), - stc(), - varargs((VarArg)0u), - hasIdentifierList() - { - } -}; - -class FuncDeclaration : public Declaration -{ -public: - Statement* fbody; - Array foverrides; -private: - ContractInfo* contracts; -public: - const char* mangleString; - VarDeclaration* vresult; - LabelDsymbol* returnLabel; - void* isTypeIsolatedCache; - DsymbolTable* localsymtab; - VarDeclaration* vthis; - VarDeclaration* v_arguments; - VarDeclaration* v_argptr; - Array* parameters; - DsymbolTable* labtab; - Dsymbol* overnext; - FuncDeclaration* overnext0; - Loc endloc; - int32_t vtblIndex; - ILS inlineStatusStmt; - ILS inlineStatusExp; - PINLINE inlining; - int32_t inlineNest; - ForeachStatement* fes; - BaseClass* interfaceVirtual; - Type* tintro; - StorageClass storage_class2; - int32_t hasReturnExp; - VarDeclaration* nrvo_var; - Symbol* shidden; - Array* returns; - Array* gotos; - Array* alignSectionVars; - Symbol* salignSection; - BUILTIN builtin; - int32_t tookAddressOf; - bool requiresClosure; - Array closureVars; - Array outerVars; - Array siblingCallers; - Array* inlinedNestedCallees; - AttributeViolation* safetyViolation; - AttributeViolation* nogcViolation; - AttributeViolation* pureViolation; - AttributeViolation* nothrowViolation; - bool purityInprocess() const; - bool purityInprocess(bool v); - bool safetyInprocess() const; - bool safetyInprocess(bool v); - bool nothrowInprocess() const; - bool nothrowInprocess(bool v); - bool nogcInprocess() const; - bool nogcInprocess(bool v); - bool returnInprocess() const; - bool returnInprocess(bool v); - bool inlineScanned() const; - bool inlineScanned(bool v); - bool inferScope() const; - bool inferScope(bool v); - bool hasCatches() const; - bool hasCatches(bool v); - bool skipCodegen() const; - bool skipCodegen(bool v); - bool printf() const; - bool printf(bool v); - bool scanf() const; - bool scanf(bool v); - bool noreturn() const; - bool noreturn(bool v); - bool isNRVO() const; - bool isNRVO(bool v); - bool isNaked() const; - bool isNaked(bool v); - bool isGenerated() const; - bool isGenerated(bool v); - bool isIntroducing() const; - bool isIntroducing(bool v); - bool hasSemantic3Errors() const; - bool hasSemantic3Errors(bool v); - bool hasNoEH() const; - bool hasNoEH(bool v); - bool inferRetType() const; - bool inferRetType(bool v); - bool hasDualContext() const; - bool hasDualContext(bool v); - bool hasAlwaysInlines() const; - bool hasAlwaysInlines(bool v); - bool isCrtCtor() const; - bool isCrtCtor(bool v); - bool isCrtDtor() const; - bool isCrtDtor(bool v); - bool hasEscapingSiblings() const; - bool hasEscapingSiblings(bool v); - bool computedEscapingSiblings() const; - bool computedEscapingSiblings(bool v); - bool dllImport() const; - bool dllImport(bool v); - bool dllExport() const; - bool dllExport(bool v); -private: - uint32_t bitFields; -public: - ObjcFuncDeclaration objc; - static FuncDeclaration* create(const Loc& loc, const Loc& endloc, Identifier* id, StorageClass storage_class, Type* type, bool noreturn = false); - Array* frequires(); - Array* fensures(); - Statement* frequire(); - Statement* fensure(); - FuncDeclaration* fdrequire(); - FuncDeclaration* fdensure(); - Array* fdrequireParams(); - Array* fdensureParams(); - Array* frequires(Array* param); - Array* fensures(Array* param); - Statement* frequire(Statement* param); - Statement* fensure(Statement* param); - FuncDeclaration* fdrequire(FuncDeclaration* param); - FuncDeclaration* fdensure(FuncDeclaration* param); - Array* fdrequireParams(Array* param); - Array* fdensureParams(Array* param); - FuncDeclaration* syntaxCopy(Dsymbol* s) override; - bool functionSemantic(); - bool functionSemantic3(); - bool equals(const RootObject* const o) const final override; - int32_t findVtblIndex(Array* vtbl, int32_t dim); - bool overloadInsert(Dsymbol* s) override; - bool inUnittest(); - MATCH leastAsSpecialized(FuncDeclaration* g, Array* names); - LabelDsymbol* searchLabel(Identifier* ident, const Loc& loc = Loc::initial); - enum : int32_t { LevelError = -2 }; - - const char* toPrettyChars(bool QualifyTypes = false) override; - const char* toFullSignature(); - bool isMain() const; - bool isCMain() const; - bool isWinMain() const; - bool isDllMain() const; - bool isRtInit() const; - bool isExport() const final override; - bool isImportedSymbol() const final override; - bool isCodeseg() const final override; - bool isOverloadable() const final override; - bool isAbstract() final override; - bool canInferAttributes(Scope* sc); - void initInferAttributes(); - PURE isPure(); - bool isSafe(); - bool isTrusted(); - bool isNogc(); - virtual bool isNested() const; - AggregateDeclaration* isThis() override; - bool needThis() final override; - bool isVirtualMethod(); - virtual bool isVirtual() const; - bool isFinalFunc() const; - virtual bool addPreInvariant(); - virtual bool addPostInvariant(); - const char* kind() const override; - bool isUnique() const; - bool needsClosure(); - bool checkClosure(); - bool hasNestedFrameRefs(); - static bool needsFensure(FuncDeclaration* fd); - void buildEnsureRequire(); - ParameterList getParameterList(); - static FuncDeclaration* genCfunc(Array* fparams, Type* treturn, const char* name, StorageClass stc = 0); - static FuncDeclaration* genCfunc(Array* fparams, Type* treturn, Identifier* id, StorageClass stc = 0); - FuncDeclaration* isFuncDeclaration() final override; - virtual FuncDeclaration* toAliasFunc(); - void accept(Visitor* v) override; -}; - -class CtorDeclaration final : public FuncDeclaration -{ -public: - bool isCpCtor; - CtorDeclaration* syntaxCopy(Dsymbol* s) override; - const char* kind() const override; - const char* toChars() const override; - bool isVirtual() const override; - bool addPreInvariant() override; - bool addPostInvariant() override; - CtorDeclaration* isCtorDeclaration() override; - void accept(Visitor* v) override; -}; - -class DtorDeclaration final : public FuncDeclaration -{ -public: - DtorDeclaration* syntaxCopy(Dsymbol* s) override; - const char* kind() const override; - const char* toChars() const override; - bool isVirtual() const override; - bool addPreInvariant() override; - bool addPostInvariant() override; - bool overloadInsert(Dsymbol* s) override; - DtorDeclaration* isDtorDeclaration() override; - void accept(Visitor* v) override; -}; - -class FuncAliasDeclaration final : public FuncDeclaration -{ -public: - FuncDeclaration* funcalias; - bool hasOverloads; - FuncAliasDeclaration* isFuncAliasDeclaration() override; - const char* kind() const override; - FuncDeclaration* toAliasFunc() override; - void accept(Visitor* v) override; -}; - -class FuncLiteralDeclaration final : public FuncDeclaration -{ -public: - TOK tok; - Type* treq; - bool deferToObj; - FuncLiteralDeclaration* syntaxCopy(Dsymbol* s) override; - bool isNested() const override; - AggregateDeclaration* isThis() override; - bool isVirtual() const override; - bool addPreInvariant() override; - bool addPostInvariant() override; - FuncLiteralDeclaration* isFuncLiteralDeclaration() override; - const char* kind() const override; - const char* toPrettyChars(bool QualifyTypes = false) override; - void accept(Visitor* v) override; -}; - -enum class FuncResolveFlag : uint8_t -{ - standard = 0u, - quiet = 1u, - overloadOnly = 2u, - ufcs = 4u, -}; - -class InvariantDeclaration final : public FuncDeclaration -{ -public: - InvariantDeclaration* syntaxCopy(Dsymbol* s) override; - bool isVirtual() const override; - bool addPreInvariant() override; - bool addPostInvariant() override; - InvariantDeclaration* isInvariantDeclaration() override; - void accept(Visitor* v) override; -}; - -class NewDeclaration final : public FuncDeclaration -{ -public: - NewDeclaration* syntaxCopy(Dsymbol* s) override; - const char* kind() const override; - bool isVirtual() const override; - bool addPreInvariant() override; - bool addPostInvariant() override; - NewDeclaration* isNewDeclaration() override; - void accept(Visitor* v) override; -}; - -class SemanticTimePermissiveVisitor : public Visitor -{ -public: - using Visitor::visit; - void visit(Dsymbol* __param_0_) override; - void visit(Parameter* __param_0_) override; - void visit(Statement* __param_0_) override; - void visit(Type* __param_0_) override; - void visit(Expression* __param_0_) override; - void visit(TemplateParameter* __param_0_) override; - void visit(Condition* __param_0_) override; - void visit(Initializer* __param_0_) override; -}; - -class StatementRewriteWalker : public SemanticTimePermissiveVisitor -{ -public: - using SemanticTimePermissiveVisitor::visit; - Statement** ps; - void visitStmt(Statement*& s); - void replaceCurrent(Statement* s); - void visit(PeelStatement* s) override; - void visit(CompoundStatement* s) override; - void visit(CompoundDeclarationStatement* s) override; - void visit(UnrolledLoopStatement* s) override; - void visit(ScopeStatement* s) override; - void visit(WhileStatement* s) override; - void visit(DoStatement* s) override; - void visit(ForStatement* s) override; - void visit(ForeachStatement* s) override; - void visit(ForeachRangeStatement* s) override; - void visit(IfStatement* s) override; - void visit(SwitchStatement* s) override; - void visit(CaseStatement* s) override; - void visit(CaseRangeStatement* s) override; - void visit(DefaultStatement* s) override; - void visit(SynchronizedStatement* s) override; - void visit(WithStatement* s) override; - void visit(TryCatchStatement* s) override; - void visit(TryFinallyStatement* s) override; - void visit(DebugStatement* s) override; - void visit(LabelStatement* s) override; -}; - -class NrvoWalker final : public StatementRewriteWalker -{ -public: - using StatementRewriteWalker::visit; - FuncDeclaration* fd; - Scope* sc; - void visit(ReturnStatement* s) override; - void visit(TryFinallyStatement* s) override; -}; - -class PostBlitDeclaration final : public FuncDeclaration -{ -public: - PostBlitDeclaration* syntaxCopy(Dsymbol* s) override; - bool isVirtual() const override; - bool addPreInvariant() override; - bool addPostInvariant() override; - bool overloadInsert(Dsymbol* s) override; - PostBlitDeclaration* isPostBlitDeclaration() override; - void accept(Visitor* v) override; -}; - -class StaticCtorDeclaration : public FuncDeclaration -{ -public: - StaticCtorDeclaration* syntaxCopy(Dsymbol* s) override; - AggregateDeclaration* isThis() final override; - bool isVirtual() const final override; - bool addPreInvariant() final override; - bool addPostInvariant() final override; - bool hasStaticCtorOrDtor() final override; - StaticCtorDeclaration* isStaticCtorDeclaration() final override; - void accept(Visitor* v) override; -}; - -class SharedStaticCtorDeclaration final : public StaticCtorDeclaration -{ -public: - SharedStaticCtorDeclaration* syntaxCopy(Dsymbol* s) override; - SharedStaticCtorDeclaration* isSharedStaticCtorDeclaration() override; - void accept(Visitor* v) override; -}; - -class StaticDtorDeclaration : public FuncDeclaration -{ -public: - VarDeclaration* vgate; - StaticDtorDeclaration* syntaxCopy(Dsymbol* s) override; - AggregateDeclaration* isThis() final override; - bool isVirtual() const final override; - bool hasStaticCtorOrDtor() final override; - bool addPreInvariant() final override; - bool addPostInvariant() final override; - StaticDtorDeclaration* isStaticDtorDeclaration() final override; - void accept(Visitor* v) override; -}; - -class SharedStaticDtorDeclaration final : public StaticDtorDeclaration -{ -public: - SharedStaticDtorDeclaration* syntaxCopy(Dsymbol* s) override; - SharedStaticDtorDeclaration* isSharedStaticDtorDeclaration() override; - void accept(Visitor* v) override; -}; - -class UnitTestDeclaration final : public FuncDeclaration -{ -public: - char* codedoc; - Array deferredNested; - UnitTestDeclaration* syntaxCopy(Dsymbol* s) override; - AggregateDeclaration* isThis() override; - bool isVirtual() const override; - bool addPreInvariant() override; - bool addPostInvariant() override; - UnitTestDeclaration* isUnitTestDeclaration() override; - void accept(Visitor* v) override; -}; - -struct HdrGenState final -{ - bool hdrgen; - bool ddoc; - bool fullDump; - bool importcHdr; - bool fullQual; - int32_t tpltMember; - int32_t autoMember; - int32_t forStmtInit; - int32_t insideFuncBody; - int32_t insideAggregate; - bool declstring; - EnumDeclaration* inEnumDecl; - HdrGenState() : - hdrgen(), - ddoc(), - fullDump(), - importcHdr(), - fullQual(), - tpltMember(), - autoMember(), - forStmtInit(), - insideFuncBody(), - insideAggregate(), - declstring(), - inEnumDecl() - { - } - HdrGenState(bool hdrgen, bool ddoc = false, bool fullDump = false, bool importcHdr = false, bool fullQual = false, int32_t tpltMember = 0, int32_t autoMember = 0, int32_t forStmtInit = 0, int32_t insideFuncBody = 0, int32_t insideAggregate = 0, bool declstring = false, EnumDeclaration* inEnumDecl = nullptr) : - hdrgen(hdrgen), - ddoc(ddoc), - fullDump(fullDump), - importcHdr(importcHdr), - fullQual(fullQual), - tpltMember(tpltMember), - autoMember(autoMember), - forStmtInit(forStmtInit), - insideFuncBody(insideFuncBody), - insideAggregate(insideAggregate), - declstring(declstring), - inEnumDecl(inEnumDecl) - {} -}; - -enum : int32_t { TEST_EMIT_ALL = 0 }; - -extern void genhdrfile(Module* m, OutBuffer& buf); - -extern void moduleToBuffer(OutBuffer& buf, Module* m); - -extern const char* parametersTypeToChars(ParameterList pl); - -extern const char* toChars(const Statement* const s); - -enum class InitKind : uint8_t -{ - void_ = 0u, - default_ = 1u, - error = 2u, - struct_ = 3u, - array = 4u, - exp = 5u, - C_ = 6u, -}; - -class Initializer : public ASTNode -{ -public: - Loc loc; - InitKind kind; - DYNCAST dyncast() const override; - ErrorInitializer* isErrorInitializer(); - VoidInitializer* isVoidInitializer(); - DefaultInitializer* isDefaultInitializer(); - StructInitializer* isStructInitializer(); - ArrayInitializer* isArrayInitializer(); - ExpInitializer* isExpInitializer(); - CInitializer* isCInitializer(); - void accept(Visitor* v) override; -}; - -class ArrayInitializer final : public Initializer -{ -public: - Array index; - Array value; - uint32_t dim; - Type* type; - bool sem; - bool isCarray; - bool isAssociativeArray() const; - void accept(Visitor* v) override; -}; - -class CInitializer final : public Initializer -{ -public: - Array initializerList; - Type* type; - bool sem; - void accept(Visitor* v) override; -}; - -class DefaultInitializer final : public Initializer -{ -public: - Type* type; - void accept(Visitor* v) override; -}; - -class ErrorInitializer final : public Initializer -{ -public: - void accept(Visitor* v) override; -}; - -class ExpInitializer final : public Initializer -{ -public: - bool expandTuples; - Expression* exp; - void accept(Visitor* v) override; -}; - -enum class NeedInterpret -{ - INITnointerpret = 0, - INITinterpret = 1, -}; - -class StructInitializer final : public Initializer -{ -public: - Array field; - Array value; - void accept(Visitor* v) override; -}; - -class VoidInitializer final : public Initializer -{ -public: - Type* type; - void accept(Visitor* v) override; -}; - -extern Initializer* initializerSemantic(Initializer* init, Scope* sc, Type*& tx, NeedInterpret needInterpret); - -extern Expression* initializerToExpression(Initializer* init, Type* itype = nullptr, const bool isCfile = false); - -enum class DotExpFlag -{ - none = 0, - gag = 1, - noDeref = 2, - noAliasThis = 4, -}; - -enum : int32_t { LOGDEFAULTINIT = 0 }; - -enum : int32_t { LOGDOTEXP = 0 }; - -enum class DiagnosticReporting : uint8_t -{ - error = 0u, - inform = 1u, - off = 2u, -}; - -enum class CppStdRevision : uint32_t -{ - cpp98 = 199711u, - cpp11 = 201103u, - cpp14 = 201402u, - cpp17 = 201703u, - cpp20 = 202002u, -}; - -struct Help final -{ - bool manual; - bool usage; - bool mcpu; - bool transition; - bool check; - bool checkAction; - bool revert; - bool preview; - bool externStd; - bool hc; - Help() : - manual(), - usage(), - mcpu(), - transition(), - check(), - checkAction(), - revert(), - preview(), - externStd(), - hc() - { - } - Help(bool manual, bool usage = false, bool mcpu = false, bool transition = false, bool check = false, bool checkAction = false, bool revert = false, bool preview = false, bool externStd = false, bool hc = false) : - manual(manual), - usage(usage), - mcpu(mcpu), - transition(transition), - check(check), - checkAction(checkAction), - revert(revert), - preview(preview), - externStd(externStd), - hc(hc) - {} -}; - -struct Verbose final -{ - bool verbose; - bool showColumns; - bool tls; - bool templates; - bool templatesListInstances; - bool gc; - bool field; - bool complex; - bool vin; - bool showGaggedErrors; - bool printErrorContext; - bool logo; - bool color; - bool cov; - MessageStyle messageStyle; - uint32_t errorLimit; - uint32_t errorSupplementLimit; - uint32_t errorSupplementCount(); - Verbose() : - verbose(), - showColumns(), - tls(), - templates(), - templatesListInstances(), - gc(), - field(), - complex(true), - vin(), - showGaggedErrors(), - printErrorContext(), - logo(), - color(), - cov(), - messageStyle((MessageStyle)0u), - errorLimit(20u), - errorSupplementLimit(6u) - { - } - Verbose(bool verbose, bool showColumns = false, bool tls = false, bool templates = false, bool templatesListInstances = false, bool gc = false, bool field = false, bool complex = true, bool vin = false, bool showGaggedErrors = false, bool printErrorContext = false, bool logo = false, bool color = false, bool cov = false, MessageStyle messageStyle = (MessageStyle)0u, uint32_t errorLimit = 20u, uint32_t errorSupplementLimit = 6u) : - verbose(verbose), - showColumns(showColumns), - tls(tls), - templates(templates), - templatesListInstances(templatesListInstances), - gc(gc), - field(field), - complex(complex), - vin(vin), - showGaggedErrors(showGaggedErrors), - printErrorContext(printErrorContext), - logo(logo), - color(color), - cov(cov), - messageStyle(messageStyle), - errorLimit(errorLimit), - errorSupplementLimit(errorSupplementLimit) - {} -}; - -enum class FeatureState : uint8_t -{ - default_ = 0u, - disabled = 1u, - enabled = 2u, -}; - -enum class CHECKENABLE : uint8_t -{ - _default = 0u, - off = 1u, - on = 2u, - safeonly = 3u, -}; - -enum class CHECKACTION : uint8_t -{ - D = 0u, - C = 1u, - halt = 2u, - context = 3u, -}; - -struct Output final -{ - bool doOutput; - bool fullOutput; - _d_dynamicArray< const char > dir; - _d_dynamicArray< const char > name; - Array files; - OutBuffer* buffer; - int32_t bufferLines; - Output() : - doOutput(), - fullOutput(), - dir(), - name(), - files(), - buffer(), - bufferLines() - { - } - Output(bool doOutput, bool fullOutput = false, _d_dynamicArray< const char > dir = {}, _d_dynamicArray< const char > name = {}, Array files = Array(), OutBuffer* buffer = nullptr, int32_t bufferLines = 0) : - doOutput(doOutput), - fullOutput(fullOutput), - dir(dir), - name(name), - files(files), - buffer(buffer), - bufferLines(bufferLines) - {} -}; - -enum class JsonFieldFlags : uint32_t -{ - none = 0u, - compilerInfo = 1u, - buildInfo = 2u, - modules = 4u, - semantics = 8u, -}; - -struct Param final -{ - bool obj; - bool multiobj; - bool trace; - bool tracegc; - bool vcg_ast; - DiagnosticReporting useDeprecated; - bool useUnitTests; - bool useInline; - bool release; - bool preservePaths; - DiagnosticReporting warnings; - bool cov; - uint8_t covPercent; - bool ctfe_cov; - bool ignoreUnsupportedPragmas; - bool useModuleInfo; - bool useTypeInfo; - bool useExceptions; - bool useGC; - bool betterC; - bool addMain; - bool allInst; - bool bitfields; - CppStdRevision cplusplus; - Help help; - Verbose v; - FeatureState useDIP25; - FeatureState useDIP1000; - bool ehnogc; - bool useDIP1021; - FeatureState fieldwise; - bool fixAliasThis; - FeatureState rvalueRefParam; - FeatureState noSharedAccess; - bool previewIn; - bool inclusiveInContracts; - bool shortenedMethods; - bool fixImmutableConv; - bool fix16997; - FeatureState dtorFields; - FeatureState systemVariables; - CHECKENABLE useInvariants; - CHECKENABLE useIn; - CHECKENABLE useOut; - CHECKENABLE useArrayBounds; - CHECKENABLE useAssert; - CHECKENABLE useSwitchError; - CHECKENABLE boundscheck; - CHECKACTION checkAction; - _d_dynamicArray< const char > argv0; - Array modFileAliasStrings; - Array* imppath; - Array* fileImppath; - _d_dynamicArray< const char > objdir; - _d_dynamicArray< const char > objname; - _d_dynamicArray< const char > libname; - Output ddoc; - Output dihdr; - Output cxxhdr; - Output json; - JsonFieldFlags jsonFieldFlags; - Output makeDeps; - Output mixinOut; - Output moduleDeps; - uint32_t debuglevel; - uint32_t versionlevel; - bool run; - Array runargs; - Array cppswitches; - const char* cpp; - Array objfiles; - Array linkswitches; - Array linkswitchIsForCC; - Array libfiles; - Array dllfiles; - _d_dynamicArray< const char > deffile; - _d_dynamicArray< const char > resfile; - _d_dynamicArray< const char > exefile; - _d_dynamicArray< const char > mapfile; - bool parsingUnittestsRequired(); - Param() : - obj(true), - multiobj(), - trace(), - tracegc(), - vcg_ast(), - useDeprecated((DiagnosticReporting)1u), - useUnitTests(), - useInline(false), - release(), - preservePaths(), - warnings((DiagnosticReporting)2u), - cov(), - covPercent(), - ctfe_cov(false), - ignoreUnsupportedPragmas(true), - useModuleInfo(true), - useTypeInfo(true), - useExceptions(true), - useGC(true), - betterC(), - addMain(), - allInst(), - bitfields(), - cplusplus((CppStdRevision)201103u), - help(), - v(), - useDIP25((FeatureState)2u), - ehnogc(), - useDIP1021(), - fixAliasThis(), - previewIn(), - inclusiveInContracts(), - shortenedMethods(true), - fixImmutableConv(), - fix16997(true), - useInvariants((CHECKENABLE)0u), - useIn((CHECKENABLE)0u), - useOut((CHECKENABLE)0u), - useArrayBounds((CHECKENABLE)0u), - useAssert((CHECKENABLE)0u), - useSwitchError((CHECKENABLE)0u), - boundscheck((CHECKENABLE)0u), - checkAction((CHECKACTION)0u), - argv0(), - modFileAliasStrings(), - imppath(), - fileImppath(), - objdir(), - objname(), - libname(), - ddoc(), - dihdr(), - cxxhdr(), - json(), - makeDeps(), - mixinOut(), - moduleDeps(), - debuglevel(), - versionlevel(), - run(), - runargs(), - cppswitches(), - cpp(), - objfiles(), - linkswitches(), - linkswitchIsForCC(), - libfiles(), - dllfiles(), - deffile(), - resfile(), - exefile(), - mapfile() - { - } - Param(bool obj, bool multiobj = false, bool trace = false, bool tracegc = false, bool vcg_ast = false, DiagnosticReporting useDeprecated = (DiagnosticReporting)1u, bool useUnitTests = false, bool useInline = false, bool release = false, bool preservePaths = false, DiagnosticReporting warnings = (DiagnosticReporting)2u, bool cov = false, uint8_t covPercent = 0u, bool ctfe_cov = false, bool ignoreUnsupportedPragmas = true, bool useModuleInfo = true, bool useTypeInfo = true, bool useExceptions = true, bool useGC = true, bool betterC = false, bool addMain = false, bool allInst = false, bool bitfields = false, CppStdRevision cplusplus = (CppStdRevision)201103u, Help help = Help(), Verbose v = Verbose(), FeatureState useDIP25 = (FeatureState)2u, FeatureState useDIP1000 = (FeatureState)0u, bool ehnogc = false, bool useDIP1021 = false, FeatureState fieldwise = (FeatureState)0u, bool fixAliasThis = false, FeatureState rvalueRefParam = (FeatureState)0u, FeatureState noSharedAccess = (FeatureState)0u, bool previewIn = false, bool inclusiveInContracts = false, bool shortenedMethods = true, bool fixImmutableConv = false, bool fix16997 = true, FeatureState dtorFields = (FeatureState)0u, FeatureState systemVariables = (FeatureState)0u, CHECKENABLE useInvariants = (CHECKENABLE)0u, CHECKENABLE useIn = (CHECKENABLE)0u, CHECKENABLE useOut = (CHECKENABLE)0u, CHECKENABLE useArrayBounds = (CHECKENABLE)0u, CHECKENABLE useAssert = (CHECKENABLE)0u, CHECKENABLE useSwitchError = (CHECKENABLE)0u, CHECKENABLE boundscheck = (CHECKENABLE)0u, CHECKACTION checkAction = (CHECKACTION)0u, _d_dynamicArray< const char > argv0 = {}, Array modFileAliasStrings = Array(), Array* imppath = nullptr, Array* fileImppath = nullptr, _d_dynamicArray< const char > objdir = {}, _d_dynamicArray< const char > objname = {}, _d_dynamicArray< const char > libname = {}, Output ddoc = Output(), Output dihdr = Output(), Output cxxhdr = Output(), Output json = Output(), JsonFieldFlags jsonFieldFlags = (JsonFieldFlags)0u, Output makeDeps = Output(), Output mixinOut = Output(), Output moduleDeps = Output(), uint32_t debuglevel = 0u, uint32_t versionlevel = 0u, bool run = false, Array runargs = Array(), Array cppswitches = Array(), const char* cpp = nullptr, Array objfiles = Array(), Array linkswitches = Array(), Array linkswitchIsForCC = Array(), Array libfiles = Array(), Array dllfiles = Array(), _d_dynamicArray< const char > deffile = {}, _d_dynamicArray< const char > resfile = {}, _d_dynamicArray< const char > exefile = {}, _d_dynamicArray< const char > mapfile = {}) : - obj(obj), - multiobj(multiobj), - trace(trace), - tracegc(tracegc), - vcg_ast(vcg_ast), - useDeprecated(useDeprecated), - useUnitTests(useUnitTests), - useInline(useInline), - release(release), - preservePaths(preservePaths), - warnings(warnings), - cov(cov), - covPercent(covPercent), - ctfe_cov(ctfe_cov), - ignoreUnsupportedPragmas(ignoreUnsupportedPragmas), - useModuleInfo(useModuleInfo), - useTypeInfo(useTypeInfo), - useExceptions(useExceptions), - useGC(useGC), - betterC(betterC), - addMain(addMain), - allInst(allInst), - bitfields(bitfields), - cplusplus(cplusplus), - help(help), - v(v), - useDIP25(useDIP25), - useDIP1000(useDIP1000), - ehnogc(ehnogc), - useDIP1021(useDIP1021), - fieldwise(fieldwise), - fixAliasThis(fixAliasThis), - rvalueRefParam(rvalueRefParam), - noSharedAccess(noSharedAccess), - previewIn(previewIn), - inclusiveInContracts(inclusiveInContracts), - shortenedMethods(shortenedMethods), - fixImmutableConv(fixImmutableConv), - fix16997(fix16997), - dtorFields(dtorFields), - systemVariables(systemVariables), - useInvariants(useInvariants), - useIn(useIn), - useOut(useOut), - useArrayBounds(useArrayBounds), - useAssert(useAssert), - useSwitchError(useSwitchError), - boundscheck(boundscheck), - checkAction(checkAction), - argv0(argv0), - modFileAliasStrings(modFileAliasStrings), - imppath(imppath), - fileImppath(fileImppath), - objdir(objdir), - objname(objname), - libname(libname), - ddoc(ddoc), - dihdr(dihdr), - cxxhdr(cxxhdr), - json(json), - jsonFieldFlags(jsonFieldFlags), - makeDeps(makeDeps), - mixinOut(mixinOut), - moduleDeps(moduleDeps), - debuglevel(debuglevel), - versionlevel(versionlevel), - run(run), - runargs(runargs), - cppswitches(cppswitches), - cpp(cpp), - objfiles(objfiles), - linkswitches(linkswitches), - linkswitchIsForCC(linkswitchIsForCC), - libfiles(libfiles), - dllfiles(dllfiles), - deffile(deffile), - resfile(resfile), - exefile(exefile), - mapfile(mapfile) - {} -}; - -struct CompileEnv final -{ - uint32_t versionNumber; - _d_dynamicArray< const char > date; - _d_dynamicArray< const char > time; - _d_dynamicArray< const char > vendor; - _d_dynamicArray< const char > timestamp; - bool previewIn; - bool ddocOutput; - bool masm; - CompileEnv() : - versionNumber(), - date(), - time(), - vendor(), - timestamp(), - previewIn(), - ddocOutput(), - masm() - { - } - CompileEnv(uint32_t versionNumber, _d_dynamicArray< const char > date = {}, _d_dynamicArray< const char > time = {}, _d_dynamicArray< const char > vendor = {}, _d_dynamicArray< const char > timestamp = {}, bool previewIn = false, bool ddocOutput = false, bool masm = false) : - versionNumber(versionNumber), - date(date), - time(time), - vendor(vendor), - timestamp(timestamp), - previewIn(previewIn), - ddocOutput(ddocOutput), - masm(masm) - {} -}; - -struct Global final -{ - _d_dynamicArray< const char > inifilename; - _d_dynamicArray< const char > copyright; - _d_dynamicArray< const char > written; - Array* path; - Array* filePath; - char datetime[26LLU]; - CompileEnv compileEnv; - Param params; - uint32_t errors; - uint32_t warnings; - uint32_t gag; - uint32_t gaggedErrors; - uint32_t gaggedWarnings; - void* console; - Array* versionids; - Array* debugids; - bool hasMainFunction; - uint32_t varSequenceNumber; - FileManager* fileManager; - enum : int32_t { recursionLimit = 500 }; - - ErrorSink* errorSink; - ErrorSink* errorSinkNull; - FileName(*preprocess)(FileName , const Loc& , bool& , OutBuffer* ); - uint32_t startGagging(); - bool endGagging(uint32_t oldGagged); - void increaseErrorCount(); - void _init(); - uint32_t versionNumber(); - const char* const versionChars(); - Global() : - inifilename(), - copyright(73, "Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved"), - written(24, "written by Walter Bright"), - path(), - filePath(), - compileEnv(), - params(), - errors(), - warnings(), - gag(), - gaggedErrors(), - gaggedWarnings(), - console(), - versionids(), - debugids(), - hasMainFunction(), - varSequenceNumber(1u), - fileManager(), - errorSink(), - errorSinkNull(), - preprocess() - { - } - Global(_d_dynamicArray< const char > inifilename, _d_dynamicArray< const char > copyright = { 73, "Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved" }, _d_dynamicArray< const char > written = { 24, "written by Walter Bright" }, Array* path = nullptr, Array* filePath = nullptr, CompileEnv compileEnv = CompileEnv(), Param params = Param(), uint32_t errors = 0u, uint32_t warnings = 0u, uint32_t gag = 0u, uint32_t gaggedErrors = 0u, uint32_t gaggedWarnings = 0u, void* console = nullptr, Array* versionids = nullptr, Array* debugids = nullptr, bool hasMainFunction = false, uint32_t varSequenceNumber = 1u, FileManager* fileManager = nullptr, ErrorSink* errorSink = nullptr, ErrorSink* errorSinkNull = nullptr, FileName(*preprocess)(FileName , const Loc& , bool& , OutBuffer* ) = nullptr) : - inifilename(inifilename), - copyright(copyright), - written(written), - path(path), - filePath(filePath), - compileEnv(compileEnv), - params(params), - errors(errors), - warnings(warnings), - gag(gag), - gaggedErrors(gaggedErrors), - gaggedWarnings(gaggedWarnings), - console(console), - versionids(versionids), - debugids(debugids), - hasMainFunction(hasMainFunction), - varSequenceNumber(varSequenceNumber), - fileManager(fileManager), - errorSink(errorSink), - errorSinkNull(errorSinkNull), - preprocess(preprocess) - {} -}; - -extern Global global; - -class Parameter final : public ASTNode -{ -public: - Loc loc; - StorageClass storageClass; - Type* type; - Identifier* ident; - Expression* defaultArg; - UserAttributeDeclaration* userAttribDecl; - static Parameter* create(const Loc& loc, StorageClass storageClass, Type* type, Identifier* ident, Expression* defaultArg, UserAttributeDeclaration* userAttribDecl); - Parameter* syntaxCopy(); - Type* isLazyArray(); - bool isLazy() const; - bool isReference() const; - DYNCAST dyncast() const override; - void accept(Visitor* v) override; - static size_t dim(Array* parameters); - static Parameter* getNth(Array* parameters, size_t nth); - const char* toChars() const override; - bool isCovariant(bool returnByRef, const Parameter* const p, bool previewIn = global.params.previewIn) const; -}; - -enum class RET -{ - regs = 1, - stack = 2, -}; - -enum : uint64_t { SIZE_INVALID = 18446744073709551615LLU }; - -enum class ScopeRef -{ - None = 0, - Scope = 1, - ReturnScope = 2, - Ref = 3, - ReturnRef = 4, - RefScope = 5, - ReturnRef_Scope = 6, - Ref_ReturnScope = 7, - Return = 8, -}; - -enum class TRUSTformat -{ - TRUSTformatDefault = 0, - TRUSTformatSystem = 1, -}; - -class TypeNext : public Type -{ -public: - Type* next; - void checkDeprecated(const Loc& loc, Scope* sc) final override; - int32_t hasWild() const final override; - Type* nextOf() final override; - Type* makeConst() final override; - Type* makeImmutable() final override; - Type* makeShared() final override; - Type* makeSharedConst() final override; - Type* makeWild() final override; - Type* makeWildConst() final override; - Type* makeSharedWild() final override; - Type* makeSharedWildConst() final override; - Type* makeMutable() final override; - MATCH constConv(Type* to) override; - uint8_t deduceWild(Type* t, bool isRef) final override; - void transitive(); - void accept(Visitor* v) override; -}; - -class TypeArray : public TypeNext -{ -public: - void accept(Visitor* v) override; -}; - -class TypeAArray final : public TypeArray -{ -public: - Type* index; - Loc loc; - static TypeAArray* create(Type* t, Type* index); - const char* kind() const override; - TypeAArray* syntaxCopy() override; - uinteger_t size(const Loc& loc) override; - bool isZeroInit(const Loc& loc) override; - bool isBoolean() override; - bool hasPointers() override; - MATCH implicitConvTo(Type* to) override; - MATCH constConv(Type* to) override; - void accept(Visitor* v) override; -}; - -class TypeBasic final : public Type -{ -public: - const char* dstring; - uint32_t flags; - const char* kind() const override; - TypeBasic* syntaxCopy() override; - uinteger_t size(const Loc& loc) override; - uint32_t alignsize() override; - bool isintegral() override; - bool isfloating() override; - bool isreal() override; - bool isimaginary() override; - bool iscomplex() override; - bool isscalar() override; - bool isunsigned() override; - MATCH implicitConvTo(Type* to) override; - bool isZeroInit(const Loc& loc) override; - TypeBasic* isTypeBasic() override; - void accept(Visitor* v) override; -}; - -enum class AliasThisRec -{ - no = 0, - yes = 1, - fwdref = 2, - typeMask = 3, - tracing = 4, - tracingDT = 8, -}; - -class TypeClass final : public Type -{ -public: - ClassDeclaration* sym; - AliasThisRec att; - CPPMANGLE cppmangle; - const char* kind() const override; - uinteger_t size(const Loc& loc) override; - TypeClass* syntaxCopy() override; - Dsymbol* toDsymbol(Scope* sc) override; - ClassDeclaration* isClassHandle() override; - bool isBaseOf(Type* t, int32_t* poffset) override; - MATCH implicitConvTo(Type* to) override; - MATCH constConv(Type* to) override; - uint8_t deduceWild(Type* t, bool isRef) override; - Type* toHeadMutable() override; - bool isZeroInit(const Loc& loc) override; - bool isscope() override; - bool isBoolean() override; - bool hasPointers() override; - void accept(Visitor* v) override; -}; - -class TypeDArray final : public TypeArray -{ -public: - const char* kind() const override; - TypeDArray* syntaxCopy() override; - uinteger_t size(const Loc& loc) override; - uint32_t alignsize() override; - bool isString() override; - bool isZeroInit(const Loc& loc) override; - bool isBoolean() override; - MATCH implicitConvTo(Type* to) override; - bool hasPointers() override; - void accept(Visitor* v) override; -}; - -class TypeDelegate final : public TypeNext -{ -public: - static TypeDelegate* create(TypeFunction* t); - const char* kind() const override; - TypeDelegate* syntaxCopy() override; - Type* addStorageClass(StorageClass stc) override; - uinteger_t size(const Loc& loc) override; - uint32_t alignsize() override; - MATCH implicitConvTo(Type* to) override; - bool isZeroInit(const Loc& loc) override; - bool isBoolean() override; - bool hasPointers() override; - void accept(Visitor* v) override; -}; - -class TypeEnum final : public Type -{ -public: - EnumDeclaration* sym; - const char* kind() const override; - TypeEnum* syntaxCopy() override; - uinteger_t size(const Loc& loc) override; - Type* memType(const Loc& loc = Loc::initial); - uint32_t alignsize() override; - Dsymbol* toDsymbol(Scope* sc) override; - bool isintegral() override; - bool isfloating() override; - bool isreal() override; - bool isimaginary() override; - bool iscomplex() override; - bool isscalar() override; - bool isunsigned() override; - bool isBoolean() override; - bool isString() override; - bool isAssignable() override; - bool needsDestruction() override; - bool needsCopyOrPostblit() override; - bool needsNested() override; - MATCH implicitConvTo(Type* to) override; - MATCH constConv(Type* to) override; - bool isZeroInit(const Loc& loc) override; - bool hasPointers() override; - bool hasVoidInitPointers() override; - bool hasSystemFields() override; - bool hasInvariant() override; - Type* nextOf() override; - void accept(Visitor* v) override; -}; - -class TypeError final : public Type -{ -public: - const char* kind() const override; - TypeError* syntaxCopy() override; - uinteger_t size(const Loc& loc) override; - Expression* defaultInitLiteral(const Loc& loc) override; - void accept(Visitor* v) override; -}; - -enum class TRUST : uint8_t -{ - default_ = 0u, - system = 1u, - trusted = 2u, - safe = 3u, -}; - -class TypeFunction final : public TypeNext -{ -public: - ParameterList parameterList; -private: - struct BitFields final - { - bool isnothrow; - bool isnogc; - bool isproperty; - bool isref; - bool isreturn; - bool isScopeQual; - bool isreturninferred; - bool isscopeinferred; - bool islive; - bool incomplete; - bool isInOutParam; - bool isInOutQual; - bool isctor; - bool isreturnscope; - BitFields() : - isnothrow(), - isnogc(), - isproperty(), - isref(), - isreturn(), - isScopeQual(), - isreturninferred(), - isscopeinferred(), - islive(), - incomplete(), - isInOutParam(), - isInOutQual(), - isctor(), - isreturnscope() - { - } - BitFields(bool isnothrow, bool isnogc = false, bool isproperty = false, bool isref = false, bool isreturn = false, bool isScopeQual = false, bool isreturninferred = false, bool isscopeinferred = false, bool islive = false, bool incomplete = false, bool isInOutParam = false, bool isInOutQual = false, bool isctor = false, bool isreturnscope = false) : - isnothrow(isnothrow), - isnogc(isnogc), - isproperty(isproperty), - isref(isref), - isreturn(isreturn), - isScopeQual(isScopeQual), - isreturninferred(isreturninferred), - isscopeinferred(isscopeinferred), - islive(islive), - incomplete(incomplete), - isInOutParam(isInOutParam), - isInOutQual(isInOutQual), - isctor(isctor), - isreturnscope(isreturnscope) - {} - }; - -public: - bool isnothrow() const; - bool isnothrow(bool v); - bool isnogc() const; - bool isnogc(bool v); - bool isproperty() const; - bool isproperty(bool v); - bool isref() const; - bool isref(bool v); - bool isreturn() const; - bool isreturn(bool v); - bool isScopeQual() const; - bool isScopeQual(bool v); - bool isreturninferred() const; - bool isreturninferred(bool v); - bool isscopeinferred() const; - bool isscopeinferred(bool v); - bool islive() const; - bool islive(bool v); - bool incomplete() const; - bool incomplete(bool v); - bool isInOutParam() const; - bool isInOutParam(bool v); - bool isInOutQual() const; - bool isInOutQual(bool v); - bool isctor() const; - bool isctor(bool v); - bool isreturnscope() const; - bool isreturnscope(bool v); -private: - uint16_t bitFields; -public: - LINK linkage; - TRUST trust; - PURE purity; - int8_t inuse; - Array* fargs; - static TypeFunction* create(Array* parameters, Type* treturn, uint8_t varargs, LINK linkage, StorageClass stc = 0); - const char* kind() const override; - TypeFunction* syntaxCopy() override; - void purityLevel(); - bool hasLazyParameters(); - bool isDstyleVariadic() const; - StorageClass parameterStorageClass(Type* tthis, Parameter* p, Array* outerVars = nullptr, bool indirect = false); - Type* addStorageClass(StorageClass stc) override; - Type* substWildTo(uint32_t __param_0_) override; - MATCH constConv(Type* to) override; - bool iswild() const; - void accept(Visitor* v) override; -}; - -class TypeQualified : public Type -{ -public: - Loc loc; - Array idents; - TypeQualified* syntaxCopy() override = 0; - uinteger_t size(const Loc& loc) override; - void accept(Visitor* v) override; -}; - -class TypeIdentifier final : public TypeQualified -{ -public: - Identifier* ident; - Dsymbol* originalSymbol; - static TypeIdentifier* create(const Loc& loc, Identifier* ident); - const char* kind() const override; - TypeIdentifier* syntaxCopy() override; - Dsymbol* toDsymbol(Scope* sc) override; - void accept(Visitor* v) override; -}; - -class TypeInstance final : public TypeQualified -{ -public: - TemplateInstance* tempinst; - const char* kind() const override; - TypeInstance* syntaxCopy() override; - Dsymbol* toDsymbol(Scope* sc) override; - void accept(Visitor* v) override; -}; - -class TypeMixin final : public Type -{ -public: - Loc loc; - Array* exps; - RootObject* obj; - const char* kind() const override; - TypeMixin* syntaxCopy() override; - Dsymbol* toDsymbol(Scope* sc) override; - void accept(Visitor* v) override; -}; - -class TypeNoreturn final : public Type -{ -public: - const char* kind() const override; - TypeNoreturn* syntaxCopy() override; - MATCH implicitConvTo(Type* to) override; - MATCH constConv(Type* to) override; - bool isBoolean() override; - uinteger_t size(const Loc& loc) override; - uint32_t alignsize() override; - void accept(Visitor* v) override; -}; - -class TypeNull final : public Type -{ -public: - const char* kind() const override; - TypeNull* syntaxCopy() override; - MATCH implicitConvTo(Type* to) override; - bool hasPointers() override; - bool isBoolean() override; - uinteger_t size(const Loc& loc) override; - void accept(Visitor* v) override; -}; - -class TypePointer final : public TypeNext -{ -public: - static TypePointer* create(Type* t); - const char* kind() const override; - TypePointer* syntaxCopy() override; - uinteger_t size(const Loc& loc) override; - MATCH implicitConvTo(Type* to) override; - MATCH constConv(Type* to) override; - bool isscalar() override; - bool isZeroInit(const Loc& loc) override; - bool hasPointers() override; - void accept(Visitor* v) override; -}; - -class TypeReference final : public TypeNext -{ -public: - const char* kind() const override; - TypeReference* syntaxCopy() override; - uinteger_t size(const Loc& loc) override; - bool isZeroInit(const Loc& loc) override; - void accept(Visitor* v) override; -}; - -class TypeReturn final : public TypeQualified -{ -public: - const char* kind() const override; - TypeReturn* syntaxCopy() override; - Dsymbol* toDsymbol(Scope* sc) override; - void accept(Visitor* v) override; -}; - -class TypeSArray final : public TypeArray -{ -public: - Expression* dim; - const char* kind() const override; - TypeSArray* syntaxCopy() override; - bool isIncomplete(); - uinteger_t size(const Loc& loc) override; - uint32_t alignsize() override; - bool isString() override; - bool isZeroInit(const Loc& loc) override; - structalign_t alignment() override; - MATCH constConv(Type* to) override; - MATCH implicitConvTo(Type* to) override; - Expression* defaultInitLiteral(const Loc& loc) override; - bool hasPointers() override; - bool hasSystemFields() override; - bool hasVoidInitPointers() override; - bool hasInvariant() override; - bool needsDestruction() override; - bool needsCopyOrPostblit() override; - bool needsNested() override; - void accept(Visitor* v) override; -}; - -class TypeSlice final : public TypeNext -{ -public: - Expression* lwr; - Expression* upr; - const char* kind() const override; - TypeSlice* syntaxCopy() override; - void accept(Visitor* v) override; -}; - -class TypeStruct final : public Type -{ -public: - StructDeclaration* sym; - AliasThisRec att; - bool inuse; - static TypeStruct* create(StructDeclaration* sym); - const char* kind() const override; - uinteger_t size(const Loc& loc) override; - uint32_t alignsize() override; - TypeStruct* syntaxCopy() override; - Dsymbol* toDsymbol(Scope* sc) override; - structalign_t alignment() override; - Expression* defaultInitLiteral(const Loc& loc) override; - bool isZeroInit(const Loc& loc) override; - bool isAssignable() override; - bool isBoolean() override; - bool needsDestruction() override; - bool needsCopyOrPostblit() override; - bool needsNested() override; - bool hasPointers() override; - bool hasVoidInitPointers() override; - bool hasSystemFields() override; - bool hasInvariant() override; - MATCH implicitConvTo(Type* to) override; - MATCH constConv(Type* to) override; - uint8_t deduceWild(Type* t, bool isRef) override; - Type* toHeadMutable() override; - void accept(Visitor* v) override; -}; - -class TypeTag final : public Type -{ -public: - Loc loc; - TOK tok; - structalign_t packalign; - Identifier* id; - Type* base; - Array* members; - Type* resolved; - uint8_t mod; - const char* kind() const override; - TypeTag* syntaxCopy() override; - void accept(Visitor* v) override; -}; - -class TypeTraits final : public Type -{ -public: - Loc loc; - TraitsExp* exp; - RootObject* obj; - const char* kind() const override; - TypeTraits* syntaxCopy() override; - Dsymbol* toDsymbol(Scope* sc) override; - void accept(Visitor* v) override; - uinteger_t size(const Loc& loc) override; -}; - -class TypeTuple final : public Type -{ -public: - static TypeTuple* empty; - Array* arguments; - static TypeTuple* create(Array* arguments); - static TypeTuple* create(); - static TypeTuple* create(Type* t1); - static TypeTuple* create(Type* t1, Type* t2); - const char* kind() const override; - TypeTuple* syntaxCopy() override; - bool equals(const RootObject* const o) const override; - MATCH implicitConvTo(Type* to) override; - void accept(Visitor* v) override; -}; - -class TypeTypeof final : public TypeQualified -{ -public: - Expression* exp; - int32_t inuse; - const char* kind() const override; - TypeTypeof* syntaxCopy() override; - Dsymbol* toDsymbol(Scope* sc) override; - uinteger_t size(const Loc& loc) override; - void accept(Visitor* v) override; -}; - -class TypeVector final : public Type -{ -public: - Type* basetype; - static TypeVector* create(Type* basetype); - const char* kind() const override; - TypeVector* syntaxCopy() override; - uinteger_t size(const Loc& loc) override; - uint32_t alignsize() override; - bool isintegral() override; - bool isfloating() override; - bool isscalar() override; - bool isunsigned() override; - bool isBoolean() override; - MATCH implicitConvTo(Type* to) override; - Expression* defaultInitLiteral(const Loc& loc) override; - TypeBasic* elementType(); - bool isZeroInit(const Loc& loc) override; - void accept(Visitor* v) override; -}; - -extern AggregateDeclaration* isAggregate(Type* t); - -class Nspace final : public ScopeDsymbol -{ -public: - Expression* identExp; - Nspace* syntaxCopy(Dsymbol* s) override; - bool hasPointers() override; - void setFieldOffset(AggregateDeclaration* ad, FieldState& fieldState, bool isunion) override; - const char* kind() const override; - Nspace* isNspace() override; - void accept(Visitor* v) override; -}; - -enum class STMT : uint8_t -{ - Error = 0u, - Peel = 1u, - Exp = 2u, - DtorExp = 3u, - Mixin = 4u, - Compound = 5u, - CompoundDeclaration = 6u, - CompoundAsm = 7u, - UnrolledLoop = 8u, - Scope = 9u, - Forwarding = 10u, - While = 11u, - Do = 12u, - For = 13u, - Foreach = 14u, - ForeachRange = 15u, - If = 16u, - Conditional = 17u, - StaticForeach = 18u, - Pragma = 19u, - StaticAssert = 20u, - Switch = 21u, - Case = 22u, - CaseRange = 23u, - Default = 24u, - GotoDefault = 25u, - GotoCase = 26u, - SwitchError = 27u, - Return = 28u, - Break = 29u, - Continue = 30u, - Synchronized = 31u, - With = 32u, - TryCatch = 33u, - TryFinally = 34u, - ScopeGuard = 35u, - Throw = 36u, - Debug = 37u, - Goto = 38u, - Label = 39u, - Asm = 40u, - InlineAsm = 41u, - GccAsm = 42u, - Import = 43u, -}; - -class Statement : public ASTNode -{ -public: - const Loc loc; - const STMT stmt; - DYNCAST dyncast() const final override; - virtual Statement* syntaxCopy(); - static Array* arraySyntaxCopy(Array* a); - virtual Statement* getRelatedLabeled(); - virtual bool hasBreak() const; - virtual bool hasContinue() const; - virtual Statement* last(); - void accept(Visitor* v) override; - virtual ReturnStatement* endsWithReturnStatement(); - ErrorStatement* isErrorStatement(); - PeelStatement* isPeelStatement(); - ScopeStatement* isScopeStatement(); - ExpStatement* isExpStatement(); - CompoundStatement* isCompoundStatement(); - ReturnStatement* isReturnStatement(); - IfStatement* isIfStatement(); - ConditionalStatement* isConditionalStatement(); - StaticForeachStatement* isStaticForeachStatement(); - CaseStatement* isCaseStatement(); - DefaultStatement* isDefaultStatement(); - LabelStatement* isLabelStatement(); - GotoStatement* isGotoStatement(); - GotoDefaultStatement* isGotoDefaultStatement(); - GotoCaseStatement* isGotoCaseStatement(); - BreakStatement* isBreakStatement(); - DtorExpStatement* isDtorExpStatement(); - MixinStatement* isMixinStatement(); - ForwardingStatement* isForwardingStatement(); - DoStatement* isDoStatement(); - WhileStatement* isWhileStatement(); - ForStatement* isForStatement(); - ForeachStatement* isForeachStatement(); - SwitchStatement* isSwitchStatement(); - ContinueStatement* isContinueStatement(); - WithStatement* isWithStatement(); - TryCatchStatement* isTryCatchStatement(); - ThrowStatement* isThrowStatement(); - DebugStatement* isDebugStatement(); - TryFinallyStatement* isTryFinallyStatement(); - ScopeGuardStatement* isScopeGuardStatement(); - SwitchErrorStatement* isSwitchErrorStatement(); - UnrolledLoopStatement* isUnrolledLoopStatement(); - ForeachRangeStatement* isForeachRangeStatement(); - CompoundDeclarationStatement* isCompoundDeclarationStatement(); - CompoundAsmStatement* isCompoundAsmStatement(); - PragmaStatement* isPragmaStatement(); - StaticAssertStatement* isStaticAssertStatement(); - CaseRangeStatement* isCaseRangeStatement(); - SynchronizedStatement* isSynchronizedStatement(); - AsmStatement* isAsmStatement(); - InlineAsmStatement* isInlineAsmStatement(); - GccAsmStatement* isGccAsmStatement(); - ImportStatement* isImportStatement(); -}; - -class AsmStatement : public Statement -{ -public: - Token* tokens; - bool caseSensitive; - AsmStatement* syntaxCopy() override; - void accept(Visitor* v) override; -}; - -class BreakStatement final : public Statement -{ -public: - Identifier* ident; - BreakStatement* syntaxCopy() override; - void accept(Visitor* v) override; -}; - -class CaseRangeStatement final : public Statement -{ -public: - Expression* first; - Expression* last; - Statement* statement; - CaseRangeStatement* syntaxCopy() override; - void accept(Visitor* v) override; -}; - -class CaseStatement final : public Statement -{ -public: - Expression* exp; - Statement* statement; - int32_t index; - VarDeclaration* lastVar; - void* extra; - CaseStatement* syntaxCopy() override; - void accept(Visitor* v) override; -}; - -class Catch final : public RootObject -{ -public: - const Loc loc; - Type* type; - Identifier* ident; - Statement* handler; - VarDeclaration* var; - bool errors; - bool internalCatch; - Catch* syntaxCopy(); -}; - -class CompoundStatement : public Statement -{ -public: - Array* statements; - static CompoundStatement* create(const Loc& loc, Statement* s1, Statement* s2); - CompoundStatement* syntaxCopy() override; - ReturnStatement* endsWithReturnStatement() final override; - Statement* last() final override; - void accept(Visitor* v) override; -}; - -class CompoundAsmStatement final : public CompoundStatement -{ -public: - StorageClass stc; - CompoundAsmStatement* syntaxCopy() override; - void accept(Visitor* v) override; -}; - -class CompoundDeclarationStatement final : public CompoundStatement -{ -public: - CompoundDeclarationStatement* syntaxCopy() override; - void accept(Visitor* v) override; -}; - -class ConditionalStatement final : public Statement -{ -public: - Condition* condition; - Statement* ifbody; - Statement* elsebody; - ConditionalStatement* syntaxCopy() override; - void accept(Visitor* v) override; -}; - -class ContinueStatement final : public Statement -{ -public: - Identifier* ident; - ContinueStatement* syntaxCopy() override; - void accept(Visitor* v) override; -}; - -class DebugStatement final : public Statement -{ -public: - Statement* statement; - DebugStatement* syntaxCopy() override; - void accept(Visitor* v) override; -}; - -class DefaultStatement final : public Statement -{ -public: - Statement* statement; - VarDeclaration* lastVar; - DefaultStatement* syntaxCopy() override; - void accept(Visitor* v) override; -}; - -class DoStatement final : public Statement -{ -public: - Statement* _body; - Expression* condition; - Loc endloc; - DoStatement* syntaxCopy() override; - bool hasBreak() const override; - bool hasContinue() const override; - void accept(Visitor* v) override; -}; - -class ExpStatement : public Statement -{ -public: - Expression* exp; - static ExpStatement* create(const Loc& loc, Expression* exp); - ExpStatement* syntaxCopy() override; - void accept(Visitor* v) override; -}; - -class DtorExpStatement final : public ExpStatement -{ -public: - VarDeclaration* var; - DtorExpStatement* syntaxCopy() override; - void accept(Visitor* v) override; -}; - -class ErrorStatement final : public Statement -{ -public: - ErrorStatement* syntaxCopy() override; - void accept(Visitor* v) override; -}; - -class ForStatement final : public Statement -{ -public: - Statement* _init; - Expression* condition; - Expression* increment; - Statement* _body; - Loc endloc; - Statement* relatedLabeled; - ForStatement* syntaxCopy() override; - Statement* getRelatedLabeled() override; - bool hasBreak() const override; - bool hasContinue() const override; - void accept(Visitor* v) override; -}; - -class ForeachRangeStatement final : public Statement -{ -public: - TOK op; - Parameter* prm; - Expression* lwr; - Expression* upr; - Statement* _body; - Loc endloc; - VarDeclaration* key; - ForeachRangeStatement* syntaxCopy() override; - bool hasBreak() const override; - bool hasContinue() const override; - void accept(Visitor* v) override; -}; - -class ForeachStatement final : public Statement -{ -public: - TOK op; - Array* parameters; - Expression* aggr; - Statement* _body; - Loc endloc; - VarDeclaration* key; - VarDeclaration* value; - FuncDeclaration* func; - Array* cases; - Array* gotos; - ForeachStatement* syntaxCopy() override; - bool hasBreak() const override; - bool hasContinue() const override; - void accept(Visitor* v) override; -}; - -class ForwardingStatement final : public Statement -{ -public: - ForwardingScopeDsymbol* sym; - Statement* statement; - ForwardingStatement* syntaxCopy() override; - void accept(Visitor* v) override; -}; - -class GccAsmStatement final : public AsmStatement -{ -public: - StorageClass stc; - Expression* insn; - Array* args; - uint32_t outputargs; - Array* names; - Array* constraints; - Array* clobbers; - Array* labels; - Array* gotos; - GccAsmStatement* syntaxCopy() override; - void accept(Visitor* v) override; -}; - -class GotoCaseStatement final : public Statement -{ -public: - Expression* exp; - CaseStatement* cs; - GotoCaseStatement* syntaxCopy() override; - void accept(Visitor* v) override; -}; - -class GotoDefaultStatement final : public Statement -{ -public: - SwitchStatement* sw; - GotoDefaultStatement* syntaxCopy() override; - void accept(Visitor* v) override; -}; - -class GotoStatement final : public Statement -{ -public: - Identifier* ident; - LabelDsymbol* label; - Statement* tryBody; - TryFinallyStatement* tf; - ScopeGuardStatement* os; - VarDeclaration* lastVar; - bool inCtfeBlock; - GotoStatement* syntaxCopy() override; - void accept(Visitor* v) override; -}; - -class IfStatement final : public Statement -{ -public: - Parameter* prm; - Expression* condition; - Statement* ifbody; - Statement* elsebody; - VarDeclaration* match; - Loc endloc; - IfStatement* syntaxCopy() override; - void accept(Visitor* v) override; - bool isIfCtfeBlock(); -}; - -class ImportStatement final : public Statement -{ -public: - Array* imports; - ImportStatement* syntaxCopy() override; - void accept(Visitor* v) override; -}; - -class InlineAsmStatement final : public AsmStatement -{ -public: - code* asmcode; - uint32_t asmalign; - uint32_t regs; - bool refparam; - bool naked; - InlineAsmStatement* syntaxCopy() override; - void accept(Visitor* v) override; -}; - -class LabelDsymbol final : public Dsymbol -{ -public: - LabelStatement* statement; - bool deleted; - bool iasm; - bool duplicated; - static LabelDsymbol* create(Identifier* ident); - LabelDsymbol* isLabel() override; - void accept(Visitor* v) override; -}; - -class LabelStatement final : public Statement -{ -public: - Identifier* ident; - Statement* statement; - Statement* tryBody; - TryFinallyStatement* tf; - ScopeGuardStatement* os; - VarDeclaration* lastVar; - Statement* gotoTarget; - void* extra; - bool breaks; - bool inCtfeBlock; - LabelStatement* syntaxCopy() override; - void accept(Visitor* v) override; -}; - -class MixinStatement final : public Statement -{ -public: - Array* exps; - MixinStatement* syntaxCopy() override; - void accept(Visitor* v) override; -}; - -class PeelStatement final : public Statement -{ -public: - Statement* s; - void accept(Visitor* v) override; -}; - -class PragmaStatement final : public Statement -{ -public: - const Identifier* const ident; - Array* args; - Statement* _body; - PragmaStatement* syntaxCopy() override; - void accept(Visitor* v) override; -}; - -class ReturnStatement final : public Statement -{ -public: - Expression* exp; - size_t caseDim; - ReturnStatement* syntaxCopy() override; - ReturnStatement* endsWithReturnStatement() override; - void accept(Visitor* v) override; -}; - -class ScopeGuardStatement final : public Statement -{ -public: - TOK tok; - Statement* statement; - ScopeGuardStatement* syntaxCopy() override; - void accept(Visitor* v) override; -}; - -class ScopeStatement final : public Statement -{ -public: - Statement* statement; - Loc endloc; - ScopeStatement* syntaxCopy() override; - ReturnStatement* endsWithReturnStatement() override; - bool hasBreak() const override; - bool hasContinue() const override; - void accept(Visitor* v) override; -}; - -class StaticAssertStatement final : public Statement -{ -public: - StaticAssert* sa; - StaticAssertStatement* syntaxCopy() override; - void accept(Visitor* v) override; -}; - -class StaticForeachStatement final : public Statement -{ -public: - StaticForeach* sfe; - StaticForeachStatement* syntaxCopy() override; - void accept(Visitor* v) override; -}; - -class SwitchErrorStatement final : public Statement -{ -public: - Expression* exp; - void accept(Visitor* v) override; -}; - -class SwitchStatement final : public Statement -{ -public: - Parameter* param; - Expression* condition; - Statement* _body; - bool isFinal; - Loc endloc; - bool hasDefault; - bool hasVars; - DefaultStatement* sdefault; - Statement* tryBody; - TryFinallyStatement* tf; - Array gotoCases; - Array* cases; - VarDeclaration* lastVar; - SwitchStatement* syntaxCopy() override; - bool hasBreak() const override; - void accept(Visitor* v) override; -}; - -class SynchronizedStatement final : public Statement -{ -public: - Expression* exp; - Statement* _body; - SynchronizedStatement* syntaxCopy() override; - bool hasBreak() const override; - bool hasContinue() const override; - void accept(Visitor* v) override; -}; - -class ThrowStatement final : public Statement -{ -public: - Expression* exp; - bool internalThrow; - ThrowStatement* syntaxCopy() override; - void accept(Visitor* v) override; -}; - -class TryCatchStatement final : public Statement -{ -public: - Statement* _body; - Array* catches; - Statement* tryBody; - TryCatchStatement* syntaxCopy() override; - bool hasBreak() const override; - void accept(Visitor* v) override; -}; - -class TryFinallyStatement final : public Statement -{ -public: - Statement* _body; - Statement* finalbody; - Statement* tryBody; - bool bodyFallsThru; - static TryFinallyStatement* create(const Loc& loc, Statement* _body, Statement* finalbody); - TryFinallyStatement* syntaxCopy() override; - bool hasBreak() const override; - bool hasContinue() const override; - void accept(Visitor* v) override; -}; - -class UnrolledLoopStatement final : public Statement -{ -public: - Array* statements; - UnrolledLoopStatement* syntaxCopy() override; - bool hasBreak() const override; - bool hasContinue() const override; - void accept(Visitor* v) override; -}; - -class WhileStatement final : public Statement -{ -public: - Parameter* param; - Expression* condition; - Statement* _body; - Loc endloc; - WhileStatement* syntaxCopy() override; - bool hasBreak() const override; - bool hasContinue() const override; - void accept(Visitor* v) override; -}; - -class WithStatement final : public Statement -{ -public: - Expression* exp; - Statement* _body; - VarDeclaration* wthis; - Loc endloc; - WithStatement* syntaxCopy() override; - void accept(Visitor* v) override; -}; - -class StaticAssert final : public Dsymbol -{ -public: - Expression* exp; - Array* msgs; - StaticAssert* syntaxCopy(Dsymbol* s) override; - bool oneMember(Dsymbol** ps, Identifier* ident) override; - const char* kind() const override; - StaticAssert* isStaticAssert() override; - void accept(Visitor* v) override; -}; - -extern Expression* defaultInit(Type* mt, const Loc& loc, const bool isCfile = false); - -extern Type* merge(Type* type); - -extern Type* typeSemantic(Type* type, const Loc& loc, Scope* sc); - -struct UnionExp final -{ - #pragma pack(push, 8) -private: - union _AnonStruct_u - { - char exp[29LLU]; - char integerexp[40LLU]; - char errorexp[29LLU]; - char realexp[48LLU]; - char complexexp[64LLU]; - char symoffexp[64LLU]; - char stringexp[51LLU]; - char arrayliteralexp[48LLU]; - char assocarrayliteralexp[56LLU]; - char structliteralexp[76LLU]; - char compoundliteralexp[40LLU]; - char nullexp[29LLU]; - char dotvarexp[49LLU]; - char addrexp[40LLU]; - char indexexp[74LLU]; - char sliceexp[65LLU]; - char vectorexp[53LLU]; - }; - #pragma pack(pop) - - // Ignoring var u alignment 8 - _AnonStruct_u u; -public: - UnionExp() : - u() - { - } -}; - -enum class MODFlags -{ - none = 0, - const_ = 1, - immutable_ = 4, - shared_ = 2, - wild = 8, - wildconst = 9, - mutable_ = 16, -}; - -enum class STC : uint64_t -{ - undefined_ = 0LLU, - static_ = 1LLU, - extern_ = 2LLU, - const_ = 4LLU, - final_ = 8LLU, - abstract_ = 16LLU, - parameter = 32LLU, - field = 64LLU, - override_ = 128LLU, - auto_ = 256LLU, - synchronized_ = 512LLU, - deprecated_ = 1024LLU, - in_ = 2048LLU, - out_ = 4096LLU, - lazy_ = 8192LLU, - foreach_ = 16384LLU, - variadic = 32768LLU, - templateparameter = 131072LLU, - ref_ = 262144LLU, - scope_ = 524288LLU, - scopeinferred = 2097152LLU, - return_ = 4194304LLU, - returnScope = 8388608LLU, - returninferred = 16777216LLU, - immutable_ = 33554432LLU, - manifest = 134217728LLU, - nodtor = 268435456LLU, - nothrow_ = 536870912LLU, - pure_ = 1073741824LLU, - tls = 2147483648LLU, - alias_ = 4294967296LLU, - shared_ = 8589934592LLU, - gshared = 17179869184LLU, - wild = 34359738368LLU, - property = 68719476736LLU, - safe = 137438953472LLU, - trusted = 274877906944LLU, - system = 549755813888LLU, - ctfe = 1099511627776LLU, - disable = 2199023255552LLU, - result = 4398046511104LLU, - nodefaultctor = 8796093022208LLU, - temp = 17592186044416LLU, - rvalue = 35184372088832LLU, - nogc = 70368744177664LLU, - autoref = 140737488355328LLU, - inference = 281474976710656LLU, - exptemp = 562949953421312LLU, - future = 1125899906842624LLU, - local = 2251799813685248LLU, - live = 4503599627370496LLU, - register_ = 9007199254740992LLU, - volatile_ = 18014398509481984LLU, - safeGroup = 962072674304LLU, - IOR = 268288LLU, - TYPECTOR = 42983227396LLU, - FUNCATTR = 4575000774574080LLU, - visibleStorageClasses = 7954966262857631LLU, - flowThruAggregate = 962072674304LLU, - flowThruFunction = 18446742978991225440LLU, -}; - -struct ASTCodegen final -{ - using AggregateDeclaration = ::AggregateDeclaration; - using ClassKind = ::ClassKind; - using MangleOverride = ::MangleOverride; - using AliasThis = ::AliasThis; - using AliasDeclarations = ::AliasDeclarations; - using BaseClasses = ::BaseClasses; - using CaseStatements = ::CaseStatements; - using Catches = ::Catches; - using ClassDeclarations = ::ClassDeclarations; - using DesigInits = ::DesigInits; - using Designators = ::Designators; - using Dsymbols = ::Dsymbols; - using DtorDeclarations = ::DtorDeclarations; - using Ensures = ::Ensures; - using Expressions = ::Expressions; - using FuncDeclarations = ::FuncDeclarations; - using GotoCaseStatements = ::GotoCaseStatements; - using GotoStatements = ::GotoStatements; - using Identifiers = ::Identifiers; - using Initializers = ::Initializers; - using Modules = ::Modules; - using Objects = ::Objects; - using Parameters = ::Parameters; - using ReturnStatements = ::ReturnStatements; - using ScopeStatements = ::ScopeStatements; - using SharedStaticDtorDeclarations = ::SharedStaticDtorDeclarations; - using Statements = ::Statements; - using StaticDtorDeclarations = ::StaticDtorDeclarations; - using Strings = ::Strings; - using TemplateInstances = ::TemplateInstances; - using TemplateParameters = ::TemplateParameters; - using Types = ::Types; - using VarDeclarations = ::VarDeclarations; - using AlignDeclaration = ::AlignDeclaration; - using AnonDeclaration = ::AnonDeclaration; - using AttribDeclaration = ::AttribDeclaration; - using CPPMangleDeclaration = ::CPPMangleDeclaration; - using CPPNamespaceDeclaration = ::CPPNamespaceDeclaration; - using ConditionalDeclaration = ::ConditionalDeclaration; - using DeprecatedDeclaration = ::DeprecatedDeclaration; - using ForwardingAttribDeclaration = ::ForwardingAttribDeclaration; - using LinkDeclaration = ::LinkDeclaration; - using MixinDeclaration = ::MixinDeclaration; - using PragmaDeclaration = ::PragmaDeclaration; - using StaticForeachDeclaration = ::StaticForeachDeclaration; - using StaticIfDeclaration = ::StaticIfDeclaration; - using StorageClassDeclaration = ::StorageClassDeclaration; - using UserAttributeDeclaration = ::UserAttributeDeclaration; - using VisibilityDeclaration = ::VisibilityDeclaration; - using Condition = ::Condition; - using DVCondition = ::DVCondition; - using DebugCondition = ::DebugCondition; - using Include = ::Include; - using StaticForeach = ::StaticForeach; - using StaticIfCondition = ::StaticIfCondition; - using VersionCondition = ::VersionCondition; - using BaseClass = ::BaseClass; - using ClassDeclaration = ::ClassDeclaration; - using ClassFlags = ::ClassFlags; - using InterfaceDeclaration = ::InterfaceDeclaration; - using AliasDeclaration = ::AliasDeclaration; - using BitFieldDeclaration = ::BitFieldDeclaration; - using Declaration = ::Declaration; - using MatchAccumulator = ::MatchAccumulator; - using OverDeclaration = ::OverDeclaration; - using SymbolDeclaration = ::SymbolDeclaration; - using ThisDeclaration = ::ThisDeclaration; - using TupleDeclaration = ::TupleDeclaration; - using TypeInfoArrayDeclaration = ::TypeInfoArrayDeclaration; - using TypeInfoAssociativeArrayDeclaration = ::TypeInfoAssociativeArrayDeclaration; - using TypeInfoClassDeclaration = ::TypeInfoClassDeclaration; - using TypeInfoConstDeclaration = ::TypeInfoConstDeclaration; - using TypeInfoDeclaration = ::TypeInfoDeclaration; - using TypeInfoDelegateDeclaration = ::TypeInfoDelegateDeclaration; - using TypeInfoEnumDeclaration = ::TypeInfoEnumDeclaration; - using TypeInfoFunctionDeclaration = ::TypeInfoFunctionDeclaration; - using TypeInfoInterfaceDeclaration = ::TypeInfoInterfaceDeclaration; - using TypeInfoInvariantDeclaration = ::TypeInfoInvariantDeclaration; - using TypeInfoPointerDeclaration = ::TypeInfoPointerDeclaration; - using TypeInfoSharedDeclaration = ::TypeInfoSharedDeclaration; - using TypeInfoStaticArrayDeclaration = ::TypeInfoStaticArrayDeclaration; - using TypeInfoStructDeclaration = ::TypeInfoStructDeclaration; - using TypeInfoTupleDeclaration = ::TypeInfoTupleDeclaration; - using TypeInfoVectorDeclaration = ::TypeInfoVectorDeclaration; - using TypeInfoWildDeclaration = ::TypeInfoWildDeclaration; - using VarDeclaration = ::VarDeclaration; - using EnumDeclaration = ::EnumDeclaration; - using EnumMember = ::EnumMember; - using Import = ::Import; - using ForeachDg = ::ForeachDg; - using Module = ::Module; - using ModuleDeclaration = ::ModuleDeclaration; - using Package = ::Package; - using StructDeclaration = ::StructDeclaration; - using StructFlags = ::StructFlags; - using UnionDeclaration = ::UnionDeclaration; - using AliasAssign = ::AliasAssign; - using ArrayScopeSymbol = ::ArrayScopeSymbol; - using Dsymbol = ::Dsymbol; - using DsymbolTable = ::DsymbolTable; - using ExpressionDsymbol = ::ExpressionDsymbol; - using FieldState = ::FieldState; - using ForwardingScopeDsymbol = ::ForwardingScopeDsymbol; - using OverloadSet = ::OverloadSet; - using PASS = ::PASS; - using ScopeDsymbol = ::ScopeDsymbol; - using SearchOpt = ::SearchOpt; - using SearchOptFlags = ::SearchOptFlags; - using Ungag = ::Ungag; - using Visibility = ::Visibility; - using WithScopeSymbol = ::WithScopeSymbol; - using TemplateAliasParameter = ::TemplateAliasParameter; - using TemplateDeclaration = ::TemplateDeclaration; - using TemplateInstance = ::TemplateInstance; - using TemplateInstanceBox = ::TemplateInstanceBox; - using TemplateMixin = ::TemplateMixin; - using TemplateParameter = ::TemplateParameter; - using TemplatePrevious = ::TemplatePrevious; - using TemplateStats = ::TemplateStats; - using TemplateThisParameter = ::TemplateThisParameter; - using TemplateTupleParameter = ::TemplateTupleParameter; - using TemplateTypeParameter = ::TemplateTypeParameter; - using TemplateValueParameter = ::TemplateValueParameter; - using Tuple = ::Tuple; - using TypeDeduced = ::TypeDeduced; - using DebugSymbol = ::DebugSymbol; - using VersionSymbol = ::VersionSymbol; - using AddAssignExp = ::AddAssignExp; - using AddExp = ::AddExp; - using AddrExp = ::AddrExp; - using AndAssignExp = ::AndAssignExp; - using AndExp = ::AndExp; - using ArgumentList = ::ArgumentList; - using ArrayExp = ::ArrayExp; - using ArrayLengthExp = ::ArrayLengthExp; - using ArrayLiteralExp = ::ArrayLiteralExp; - using AssertExp = ::AssertExp; - using AssignExp = ::AssignExp; - using AssocArrayLiteralExp = ::AssocArrayLiteralExp; - using BinAssignExp = ::BinAssignExp; - using BinExp = ::BinExp; - using BlitExp = ::BlitExp; - using CTFEExp = ::CTFEExp; - using CallExp = ::CallExp; - using CastExp = ::CastExp; - using CatAssignExp = ::CatAssignExp; - using CatDcharAssignExp = ::CatDcharAssignExp; - using CatElemAssignExp = ::CatElemAssignExp; - using CatExp = ::CatExp; - using ClassReferenceExp = ::ClassReferenceExp; - using CmpExp = ::CmpExp; - using ComExp = ::ComExp; - using CommaExp = ::CommaExp; - using ComplexExp = ::ComplexExp; - using CompoundLiteralExp = ::CompoundLiteralExp; - using CondExp = ::CondExp; - using ConstructExp = ::ConstructExp; - using DeclarationExp = ::DeclarationExp; - using DefaultInitExp = ::DefaultInitExp; - using DelegateExp = ::DelegateExp; - using DelegateFuncptrExp = ::DelegateFuncptrExp; - using DelegatePtrExp = ::DelegatePtrExp; - using DeleteExp = ::DeleteExp; - using DivAssignExp = ::DivAssignExp; - using DivExp = ::DivExp; - using DollarExp = ::DollarExp; - using DotExp = ::DotExp; - using DotIdExp = ::DotIdExp; - using DotTemplateExp = ::DotTemplateExp; - using DotTemplateInstanceExp = ::DotTemplateInstanceExp; - using DotTypeExp = ::DotTypeExp; - using DotVarExp = ::DotVarExp; - using DsymbolExp = ::DsymbolExp; - using EqualExp = ::EqualExp; - using ErrorExp = ::ErrorExp; - using Expression = ::Expression; - using FileInitExp = ::FileInitExp; - using FuncExp = ::FuncExp; - using FuncInitExp = ::FuncInitExp; - using GenericExp = ::GenericExp; - using HaltExp = ::HaltExp; - using IdentifierExp = ::IdentifierExp; - using IdentityExp = ::IdentityExp; - using ImportExp = ::ImportExp; - using InExp = ::InExp; - using IndexExp = ::IndexExp; - using IntegerExp = ::IntegerExp; - using IntervalExp = ::IntervalExp; - using IsExp = ::IsExp; - using LineInitExp = ::LineInitExp; - using LogicalExp = ::LogicalExp; - using LoweredAssignExp = ::LoweredAssignExp; - using MemorySet = ::MemorySet; - using MinAssignExp = ::MinAssignExp; - using MinExp = ::MinExp; - using MixinExp = ::MixinExp; - using ModAssignExp = ::ModAssignExp; - using ModExp = ::ModExp; - using Modifiable = ::Modifiable; - using ModifyFlags = ::ModifyFlags; - using ModuleInitExp = ::ModuleInitExp; - using MulAssignExp = ::MulAssignExp; - using MulExp = ::MulExp; - using NegExp = ::NegExp; - using NewAnonClassExp = ::NewAnonClassExp; - using NewExp = ::NewExp; - using NotExp = ::NotExp; - using NullExp = ::NullExp; - using ObjcClassReferenceExp = ::ObjcClassReferenceExp; - using OrAssignExp = ::OrAssignExp; - using OrExp = ::OrExp; - using OverExp = ::OverExp; - using OwnedBy = ::OwnedBy; - using PostExp = ::PostExp; - using PowAssignExp = ::PowAssignExp; - using PowExp = ::PowExp; - using PreExp = ::PreExp; - using PrettyFuncInitExp = ::PrettyFuncInitExp; - using PtrExp = ::PtrExp; - using RealExp = ::RealExp; - using RemoveExp = ::RemoveExp; - using ScopeExp = ::ScopeExp; - using ShlAssignExp = ::ShlAssignExp; - using ShlExp = ::ShlExp; - using ShrAssignExp = ::ShrAssignExp; - using ShrExp = ::ShrExp; - using SliceExp = ::SliceExp; - using StringExp = ::StringExp; - using StructLiteralExp = ::StructLiteralExp; - using SuperExp = ::SuperExp; - using SymOffExp = ::SymOffExp; - using SymbolExp = ::SymbolExp; - using TemplateExp = ::TemplateExp; - using ThisExp = ::ThisExp; - using ThrowExp = ::ThrowExp; - using ThrownExceptionExp = ::ThrownExceptionExp; - using TraitsExp = ::TraitsExp; - using TupleExp = ::TupleExp; - using TypeExp = ::TypeExp; - using TypeidExp = ::TypeidExp; - using UAddExp = ::UAddExp; - using UnaExp = ::UnaExp; - using UshrAssignExp = ::UshrAssignExp; - using UshrExp = ::UshrExp; - using VarExp = ::VarExp; - using VectorArrayExp = ::VectorArrayExp; - using VectorExp = ::VectorExp; - using VoidInitExp = ::VoidInitExp; - using XorAssignExp = ::XorAssignExp; - using XorExp = ::XorExp; - using AttributeViolation = ::AttributeViolation; - using BUILTIN = ::BUILTIN; - using CtorDeclaration = ::CtorDeclaration; - using DtorDeclaration = ::DtorDeclaration; - using Ensure = ::Ensure; - using FuncAliasDeclaration = ::FuncAliasDeclaration; - using FuncDeclaration = ::FuncDeclaration; - using FuncLiteralDeclaration = ::FuncLiteralDeclaration; - using FuncResolveFlag = ::FuncResolveFlag; - using ILS = ::ILS; - using InvariantDeclaration = ::InvariantDeclaration; - using NewDeclaration = ::NewDeclaration; - using NrvoWalker = ::NrvoWalker; - using PostBlitDeclaration = ::PostBlitDeclaration; - using SharedStaticCtorDeclaration = ::SharedStaticCtorDeclaration; - using SharedStaticDtorDeclaration = ::SharedStaticDtorDeclaration; - using StaticCtorDeclaration = ::StaticCtorDeclaration; - using StaticDtorDeclaration = ::StaticDtorDeclaration; - using UnitTestDeclaration = ::UnitTestDeclaration; - using HdrGenState = ::HdrGenState; - using ArrayInitializer = ::ArrayInitializer; - using CInitializer = ::CInitializer; - using DefaultInitializer = ::DefaultInitializer; - using DesigInit = ::DesigInit; - using Designator = ::Designator; - using ErrorInitializer = ::ErrorInitializer; - using ExpInitializer = ::ExpInitializer; - using Initializer = ::Initializer; - using NeedInterpret = ::NeedInterpret; - using StructInitializer = ::StructInitializer; - using VisitInitializer = ::VisitInitializer; - using VoidInitializer = ::VoidInitializer; - using Covariant = ::Covariant; - using DotExpFlag = ::DotExpFlag; - using Parameter = ::Parameter; - using ParameterList = ::ParameterList; - using RET = ::RET; - using ScopeRef = ::ScopeRef; - using TRUSTformat = ::TRUSTformat; - using Type = ::Type; - using TypeAArray = ::TypeAArray; - using TypeArray = ::TypeArray; - using TypeBasic = ::TypeBasic; - using TypeClass = ::TypeClass; - using TypeDArray = ::TypeDArray; - using TypeDelegate = ::TypeDelegate; - using TypeEnum = ::TypeEnum; - using TypeError = ::TypeError; - using TypeFunction = ::TypeFunction; - using TypeIdentifier = ::TypeIdentifier; - using TypeInstance = ::TypeInstance; - using TypeMixin = ::TypeMixin; - using TypeNext = ::TypeNext; - using TypeNoreturn = ::TypeNoreturn; - using TypeNull = ::TypeNull; - using TypePointer = ::TypePointer; - using TypeQualified = ::TypeQualified; - using TypeReference = ::TypeReference; - using TypeReturn = ::TypeReturn; - using TypeSArray = ::TypeSArray; - using TypeSlice = ::TypeSlice; - using TypeStruct = ::TypeStruct; - using TypeTag = ::TypeTag; - using TypeTraits = ::TypeTraits; - using TypeTuple = ::TypeTuple; - using TypeTypeof = ::TypeTypeof; - using TypeVector = ::TypeVector; - using VisitType = ::VisitType; - using Nspace = ::Nspace; - using AsmStatement = ::AsmStatement; - using BreakStatement = ::BreakStatement; - using CaseRangeStatement = ::CaseRangeStatement; - using CaseStatement = ::CaseStatement; - using Catch = ::Catch; - using CompoundAsmStatement = ::CompoundAsmStatement; - using CompoundDeclarationStatement = ::CompoundDeclarationStatement; - using CompoundStatement = ::CompoundStatement; - using ConditionalStatement = ::ConditionalStatement; - using ContinueStatement = ::ContinueStatement; - using DebugStatement = ::DebugStatement; - using DefaultStatement = ::DefaultStatement; - using DoStatement = ::DoStatement; - using DtorExpStatement = ::DtorExpStatement; - using ErrorStatement = ::ErrorStatement; - using ExpStatement = ::ExpStatement; - using ForStatement = ::ForStatement; - using ForeachRangeStatement = ::ForeachRangeStatement; - using ForeachStatement = ::ForeachStatement; - using ForwardingStatement = ::ForwardingStatement; - using GccAsmStatement = ::GccAsmStatement; - using GotoCaseStatement = ::GotoCaseStatement; - using GotoDefaultStatement = ::GotoDefaultStatement; - using GotoStatement = ::GotoStatement; - using IfStatement = ::IfStatement; - using ImportStatement = ::ImportStatement; - using InlineAsmStatement = ::InlineAsmStatement; - using LabelDsymbol = ::LabelDsymbol; - using LabelStatement = ::LabelStatement; - using MixinStatement = ::MixinStatement; - using PeelStatement = ::PeelStatement; - using PragmaStatement = ::PragmaStatement; - using ReturnStatement = ::ReturnStatement; - using ScopeGuardStatement = ::ScopeGuardStatement; - using ScopeStatement = ::ScopeStatement; - using Statement = ::Statement; - using StaticAssertStatement = ::StaticAssertStatement; - using StaticForeachStatement = ::StaticForeachStatement; - using SwitchErrorStatement = ::SwitchErrorStatement; - using SwitchStatement = ::SwitchStatement; - using SynchronizedStatement = ::SynchronizedStatement; - using ThrowStatement = ::ThrowStatement; - using TryCatchStatement = ::TryCatchStatement; - using TryFinallyStatement = ::TryFinallyStatement; - using UnrolledLoopStatement = ::UnrolledLoopStatement; - using VisitStatement = ::VisitStatement; - using WhileStatement = ::WhileStatement; - using WithStatement = ::WithStatement; - using StaticAssert = ::StaticAssert; - using UnionExp = ::UnionExp; - using emplaceExp = ::emplaceExp; - typedef UserAttributeDeclaration* UserAttributeDeclaration; - typedef Ensure Ensure; - typedef ErrorExp* ErrorExp; - typedef MODFlags MODFlags; - typedef Type* Type; - typedef Parameter* Parameter; - typedef ParameterList ParameterList; - typedef VarArg VarArg; - typedef STC STC; - typedef Dsymbol* Dsymbol; - typedef Array Dsymbols; - typedef Visibility Visibility; - typedef SearchOpt SearchOpt; - typedef PASS PASS; - ASTCodegen() + virtual void visit(typename AST::Dsymbol ); + virtual void visit(typename AST::Parameter ); + virtual void visit(typename AST::Statement ); + virtual void visit(typename AST::Type ); + virtual void visit(typename AST::Expression ); + virtual void visit(typename AST::TemplateParameter ); + virtual void visit(typename AST::Condition ); + virtual void visit(typename AST::Initializer ); + virtual void visit(typename AST::AliasThis s); + virtual void visit(typename AST::Declaration s); + virtual void visit(typename AST::ScopeDsymbol s); + virtual void visit(typename AST::Import s); + virtual void visit(typename AST::AttribDeclaration s); + virtual void visit(typename AST::StaticAssert s); + virtual void visit(typename AST::DebugSymbol s); + virtual void visit(typename AST::VersionSymbol s); + virtual void visit(typename AST::AliasAssign s); + virtual void visit(typename AST::Package s); + virtual void visit(typename AST::EnumDeclaration s); + virtual void visit(typename AST::AggregateDeclaration s); + virtual void visit(typename AST::TemplateDeclaration s); + virtual void visit(typename AST::TemplateInstance s); + virtual void visit(typename AST::Nspace s); + virtual void visit(typename AST::VarDeclaration s); + virtual void visit(typename AST::FuncDeclaration s); + virtual void visit(typename AST::AliasDeclaration s); + virtual void visit(typename AST::TupleDeclaration s); + virtual void visit(typename AST::FuncLiteralDeclaration s); + virtual void visit(typename AST::PostBlitDeclaration s); + virtual void visit(typename AST::CtorDeclaration s); + virtual void visit(typename AST::DtorDeclaration s); + virtual void visit(typename AST::InvariantDeclaration s); + virtual void visit(typename AST::UnitTestDeclaration s); + virtual void visit(typename AST::NewDeclaration s); + virtual void visit(typename AST::StaticCtorDeclaration s); + virtual void visit(typename AST::StaticDtorDeclaration s); + virtual void visit(typename AST::SharedStaticCtorDeclaration s); + virtual void visit(typename AST::SharedStaticDtorDeclaration s); + virtual void visit(typename AST::MixinDeclaration s); + virtual void visit(typename AST::UserAttributeDeclaration s); + virtual void visit(typename AST::LinkDeclaration s); + virtual void visit(typename AST::AnonDeclaration s); + virtual void visit(typename AST::AlignDeclaration s); + virtual void visit(typename AST::CPPMangleDeclaration s); + virtual void visit(typename AST::CPPNamespaceDeclaration s); + virtual void visit(typename AST::VisibilityDeclaration s); + virtual void visit(typename AST::PragmaDeclaration s); + virtual void visit(typename AST::StorageClassDeclaration s); + virtual void visit(typename AST::ConditionalDeclaration s); + virtual void visit(typename AST::StaticForeachDeclaration s); + virtual void visit(typename AST::DeprecatedDeclaration s); + virtual void visit(typename AST::StaticIfDeclaration s); + virtual void visit(typename AST::EnumMember s); + virtual void visit(typename AST::Module s); + virtual void visit(typename AST::StructDeclaration s); + virtual void visit(typename AST::UnionDeclaration s); + virtual void visit(typename AST::ClassDeclaration s); + virtual void visit(typename AST::InterfaceDeclaration s); + virtual void visit(typename AST::TemplateMixin s); + virtual void visit(typename AST::BitFieldDeclaration s); + virtual void visit(typename AST::ImportStatement s); + virtual void visit(typename AST::ScopeStatement s); + virtual void visit(typename AST::ReturnStatement s); + virtual void visit(typename AST::LabelStatement s); + virtual void visit(typename AST::StaticAssertStatement s); + virtual void visit(typename AST::MixinStatement s); + virtual void visit(typename AST::WhileStatement s); + virtual void visit(typename AST::ForStatement s); + virtual void visit(typename AST::DoStatement s); + virtual void visit(typename AST::ForeachRangeStatement s); + virtual void visit(typename AST::ForeachStatement s); + virtual void visit(typename AST::IfStatement s); + virtual void visit(typename AST::ScopeGuardStatement s); + virtual void visit(typename AST::ConditionalStatement s); + virtual void visit(typename AST::StaticForeachStatement s); + virtual void visit(typename AST::PragmaStatement s); + virtual void visit(typename AST::SwitchStatement s); + virtual void visit(typename AST::CaseRangeStatement s); + virtual void visit(typename AST::CaseStatement s); + virtual void visit(typename AST::DefaultStatement s); + virtual void visit(typename AST::BreakStatement s); + virtual void visit(typename AST::ContinueStatement s); + virtual void visit(typename AST::GotoDefaultStatement s); + virtual void visit(typename AST::GotoCaseStatement s); + virtual void visit(typename AST::GotoStatement s); + virtual void visit(typename AST::SynchronizedStatement s); + virtual void visit(typename AST::WithStatement s); + virtual void visit(typename AST::TryCatchStatement s); + virtual void visit(typename AST::TryFinallyStatement s); + virtual void visit(typename AST::ThrowStatement s); + virtual void visit(typename AST::AsmStatement s); + virtual void visit(typename AST::ExpStatement s); + virtual void visit(typename AST::CompoundStatement s); + virtual void visit(typename AST::CompoundDeclarationStatement s); + virtual void visit(typename AST::CompoundAsmStatement s); + virtual void visit(typename AST::InlineAsmStatement s); + virtual void visit(typename AST::GccAsmStatement s); + virtual void visit(typename AST::TypeBasic t); + virtual void visit(typename AST::TypeError t); + virtual void visit(typename AST::TypeNull t); + virtual void visit(typename AST::TypeNoreturn t); + virtual void visit(typename AST::TypeVector t); + virtual void visit(typename AST::TypeEnum t); + virtual void visit(typename AST::TypeTuple t); + virtual void visit(typename AST::TypeClass t); + virtual void visit(typename AST::TypeStruct t); + virtual void visit(typename AST::TypeNext t); + virtual void visit(typename AST::TypeQualified t); + virtual void visit(typename AST::TypeTraits t); + virtual void visit(typename AST::TypeMixin t); + virtual void visit(typename AST::TypeTag t); + virtual void visit(typename AST::TypeReference t); + virtual void visit(typename AST::TypeSlice t); + virtual void visit(typename AST::TypeDelegate t); + virtual void visit(typename AST::TypePointer t); + virtual void visit(typename AST::TypeFunction t); + virtual void visit(typename AST::TypeArray t); + virtual void visit(typename AST::TypeDArray t); + virtual void visit(typename AST::TypeAArray t); + virtual void visit(typename AST::TypeSArray t); + virtual void visit(typename AST::TypeIdentifier t); + virtual void visit(typename AST::TypeReturn t); + virtual void visit(typename AST::TypeTypeof t); + virtual void visit(typename AST::TypeInstance t); + virtual void visit(typename AST::DeclarationExp e); + virtual void visit(typename AST::IntegerExp e); + virtual void visit(typename AST::NewAnonClassExp e); + virtual void visit(typename AST::IsExp e); + virtual void visit(typename AST::RealExp e); + virtual void visit(typename AST::NullExp e); + virtual void visit(typename AST::TypeidExp e); + virtual void visit(typename AST::TraitsExp e); + virtual void visit(typename AST::StringExp e); + virtual void visit(typename AST::NewExp e); + virtual void visit(typename AST::AssocArrayLiteralExp e); + virtual void visit(typename AST::ArrayLiteralExp e); + virtual void visit(typename AST::MixinExp e); + virtual void visit(typename AST::FuncExp e); + virtual void visit(typename AST::IntervalExp e); + virtual void visit(typename AST::TypeExp e); + virtual void visit(typename AST::ScopeExp e); + virtual void visit(typename AST::IdentifierExp e); + virtual void visit(typename AST::UnaExp e); + virtual void visit(typename AST::DefaultInitExp e); + virtual void visit(typename AST::BinExp e); + virtual void visit(typename AST::DsymbolExp e); + virtual void visit(typename AST::TemplateExp e); + virtual void visit(typename AST::SymbolExp e); + virtual void visit(typename AST::TupleExp e); + virtual void visit(typename AST::ThisExp e); + virtual void visit(typename AST::GenericExp e); + virtual void visit(typename AST::VarExp e); + virtual void visit(typename AST::DollarExp e); + virtual void visit(typename AST::SuperExp e); + virtual void visit(typename AST::AddrExp e); + virtual void visit(typename AST::PreExp e); + virtual void visit(typename AST::PtrExp e); + virtual void visit(typename AST::NegExp e); + virtual void visit(typename AST::UAddExp e); + virtual void visit(typename AST::NotExp e); + virtual void visit(typename AST::ComExp e); + virtual void visit(typename AST::DeleteExp e); + virtual void visit(typename AST::CastExp e); + virtual void visit(typename AST::CallExp e); + virtual void visit(typename AST::DotIdExp e); + virtual void visit(typename AST::AssertExp e); + virtual void visit(typename AST::ThrowExp e); + virtual void visit(typename AST::ImportExp e); + virtual void visit(typename AST::DotTemplateInstanceExp e); + virtual void visit(typename AST::ArrayExp e); + virtual void visit(typename AST::FuncInitExp e); + virtual void visit(typename AST::PrettyFuncInitExp e); + virtual void visit(typename AST::FileInitExp e); + virtual void visit(typename AST::LineInitExp e); + virtual void visit(typename AST::ModuleInitExp e); + virtual void visit(typename AST::CommaExp e); + virtual void visit(typename AST::PostExp e); + virtual void visit(typename AST::PowExp e); + virtual void visit(typename AST::MulExp e); + virtual void visit(typename AST::DivExp e); + virtual void visit(typename AST::ModExp e); + virtual void visit(typename AST::AddExp e); + virtual void visit(typename AST::MinExp e); + virtual void visit(typename AST::CatExp e); + virtual void visit(typename AST::ShlExp e); + virtual void visit(typename AST::ShrExp e); + virtual void visit(typename AST::UshrExp e); + virtual void visit(typename AST::EqualExp e); + virtual void visit(typename AST::InExp e); + virtual void visit(typename AST::IdentityExp e); + virtual void visit(typename AST::CmpExp e); + virtual void visit(typename AST::AndExp e); + virtual void visit(typename AST::XorExp e); + virtual void visit(typename AST::OrExp e); + virtual void visit(typename AST::LogicalExp e); + virtual void visit(typename AST::CondExp e); + virtual void visit(typename AST::AssignExp e); + virtual void visit(typename AST::BinAssignExp e); + virtual void visit(typename AST::AddAssignExp e); + virtual void visit(typename AST::MinAssignExp e); + virtual void visit(typename AST::MulAssignExp e); + virtual void visit(typename AST::DivAssignExp e); + virtual void visit(typename AST::ModAssignExp e); + virtual void visit(typename AST::PowAssignExp e); + virtual void visit(typename AST::AndAssignExp e); + virtual void visit(typename AST::OrAssignExp e); + virtual void visit(typename AST::XorAssignExp e); + virtual void visit(typename AST::ShlAssignExp e); + virtual void visit(typename AST::ShrAssignExp e); + virtual void visit(typename AST::UshrAssignExp e); + virtual void visit(typename AST::CatAssignExp e); + virtual void visit(typename AST::CatElemAssignExp e); + virtual void visit(typename AST::CatDcharAssignExp e); + virtual void visit(typename AST::TemplateAliasParameter tp); + virtual void visit(typename AST::TemplateTypeParameter tp); + virtual void visit(typename AST::TemplateTupleParameter tp); + virtual void visit(typename AST::TemplateValueParameter tp); + virtual void visit(typename AST::TemplateThisParameter tp); + virtual void visit(typename AST::StaticIfCondition c); + virtual void visit(typename AST::DVCondition c); + virtual void visit(typename AST::DebugCondition c); + virtual void visit(typename AST::VersionCondition c); + virtual void visit(typename AST::ExpInitializer i); + virtual void visit(typename AST::StructInitializer i); + virtual void visit(typename AST::ArrayInitializer i); + virtual void visit(typename AST::VoidInitializer i); + virtual void visit(typename AST::DefaultInitializer i); + virtual void visit(typename AST::CInitializer i); +}; + +struct MangleOverride final +{ + Dsymbol* agg; + Identifier* id; + MangleOverride() : + agg(), + id() + { + } + MangleOverride(Dsymbol* agg, Identifier* id = nullptr) : + agg(agg), + id(id) + {} +}; + +typedef Array AliasDeclarations; + +typedef Array BaseClasses; + +typedef Array CaseStatements; + +typedef Array Catches; + +typedef Array ClassDeclarations; + +struct DesigInit final +{ + Array* designatorList; + Initializer* initializer; + DesigInit() : + designatorList(), + initializer() + { + } + DesigInit(Array* designatorList, Initializer* initializer = nullptr) : + designatorList(designatorList), + initializer(initializer) + {} +}; + +typedef Array DesigInits; + +struct Designator final +{ + Expression* exp; + Identifier* ident; + Designator() : + exp(), + ident() + { + } +}; + +typedef Array Designators; + +typedef Array Dsymbols; + +typedef Array DtorDeclarations; + +struct Ensure final +{ + Identifier* id; + Statement* ensure; + Ensure syntaxCopy(); + static Array* arraySyntaxCopy(Array* a); + Ensure() : + id(), + ensure() + { + } + Ensure(Identifier* id, Statement* ensure = nullptr) : + id(id), + ensure(ensure) + {} +}; + +typedef Array Ensures; + +typedef Array Expressions; + +typedef Array FuncDeclarations; + +typedef Array GotoCaseStatements; + +typedef Array GotoStatements; + +typedef Array Identifiers; + +typedef Array Initializers; + +typedef Array Modules; + +typedef Array Objects; + +typedef Array Parameters; + +typedef Array ReturnStatements; + +typedef Array ScopeStatements; + +typedef Array SharedStaticDtorDeclarations; + +typedef Array Statements; + +typedef Array StaticDtorDeclarations; + +typedef Array Strings; + +typedef Array TemplateInstances; + +typedef Array TemplateParameters; + +typedef Array Types; + +typedef Array VarDeclarations; + +enum class ClassFlags : uint32_t +{ + none = 0u, + isCOMclass = 1u, + noPointers = 2u, + hasOffTi = 4u, + hasCtor = 8u, + hasGetMembers = 16u, + hasTypeInfo = 32u, + isAbstract = 64u, + isCPPclass = 128u, + hasDtor = 256u, +}; + +struct MatchAccumulator final +{ + int32_t count; + MATCH last; + FuncDeclaration* lastf; + FuncDeclaration* nextf; + MatchAccumulator() : + count(), + last((MATCH)0), + lastf(), + nextf() + { + } + MatchAccumulator(int32_t count, MATCH last = (MATCH)0, FuncDeclaration* lastf = nullptr, FuncDeclaration* nextf = nullptr) : + count(count), + last(last), + lastf(lastf), + nextf(nextf) + {} +}; + +enum class StructFlags +{ + none = 0, + hasPointers = 1, +}; + +struct FieldState final +{ + uint32_t offset; + uint32_t fieldOffset; + uint32_t fieldSize; + uint32_t fieldAlign; + uint32_t bitOffset; + bool inFlight; + FieldState() : + offset(), + fieldOffset(), + fieldSize(), + fieldAlign(), + bitOffset(), + inFlight() + { + } + FieldState(uint32_t offset, uint32_t fieldOffset = 0u, uint32_t fieldSize = 0u, uint32_t fieldAlign = 0u, uint32_t bitOffset = 0u, bool inFlight = false) : + offset(offset), + fieldOffset(fieldOffset), + fieldSize(fieldSize), + fieldAlign(fieldAlign), + bitOffset(bitOffset), + inFlight(inFlight) + {} +}; + +enum class SearchOpt : uint32_t +{ + all = 0u, + ignorePrivateImports = 1u, + ignoreErrors = 2u, + ignoreAmbiguous = 4u, + localsOnly = 8u, + importsOnly = 16u, + unqualifiedModule = 32u, + tagNameSpace = 64u, + ignoreVisibility = 128u, +}; + +typedef uint32_t SearchOptFlags; + +enum : int32_t { IDX_NOTFOUND = 305419896 }; + +class TemplateParameter : public ASTNode +{ +public: + Loc loc; + Identifier* ident; + bool dependent; + virtual TemplateTypeParameter* isTemplateTypeParameter(); + virtual TemplateValueParameter* isTemplateValueParameter(); + virtual TemplateAliasParameter* isTemplateAliasParameter(); + virtual TemplateThisParameter* isTemplateThisParameter(); + virtual TemplateTupleParameter* isTemplateTupleParameter(); + virtual TemplateParameter* syntaxCopy() = 0; + virtual bool declareParameter(Scope* sc) = 0; + virtual void print(RootObject* oarg, RootObject* oded) = 0; + virtual RootObject* specialization() = 0; + virtual RootObject* defaultArg(const Loc& instLoc, Scope* sc) = 0; + virtual bool hasDefaultArg() = 0; + const char* toChars() const override; + DYNCAST dyncast() const override; + virtual RootObject* dummyArg() = 0; + void accept(Visitor* v) override; +}; + +class TemplateAliasParameter final : public TemplateParameter +{ +public: + Type* specType; + RootObject* specAlias; + RootObject* defaultAlias; + TemplateAliasParameter* isTemplateAliasParameter() override; + TemplateAliasParameter* syntaxCopy() override; + bool declareParameter(Scope* sc) override; + void print(RootObject* oarg, RootObject* oded) override; + RootObject* specialization() override; + RootObject* defaultArg(const Loc& instLoc, Scope* sc) override; + bool hasDefaultArg() override; + RootObject* dummyArg() override; + void accept(Visitor* v) override; +}; + +class TemplateDeclaration final : public ScopeDsymbol +{ +public: + Array* parameters; + Array* origParameters; + Expression* constraint; + void* instances; + TemplateDeclaration* overnext; + TemplateDeclaration* overroot; + FuncDeclaration* funcroot; + Dsymbol* onemember; + bool literal; + bool ismixin; + bool isstatic; + bool isTrivialAliasSeq; + bool isTrivialAlias; + bool deprecated_; + Visibility visibility; + TemplatePrevious* previous; +private: + Expression* lastConstraint; + Array lastConstraintNegs; + Array* lastConstraintTiargs; +public: + TemplateDeclaration* syntaxCopy(Dsymbol* __param_0_) override; + bool overloadInsert(Dsymbol* s) override; + bool hasStaticCtorOrDtor() override; + const char* kind() const override; + const char* toChars() const override; + const char* toCharsNoConstraints() const; + const char* toCharsMaybeConstraints(bool includeConstraints) const; + Visibility visible() override; + const char* getConstraintEvalError(const char*& tip); + Scope* scopeForTemplateParameters(TemplateInstance* ti, Scope* sc); + TemplateDeclaration* isTemplateDeclaration() override; + bool isDeprecated() const override; + bool isOverloadable() const override; + void accept(Visitor* v) override; +}; + +class TemplateInstance : public ScopeDsymbol +{ +public: + Identifier* name; + Array* tiargs; + Array tdtypes; + Array importedModules; + Dsymbol* tempdecl; + Dsymbol* enclosing; + Dsymbol* aliasdecl; + TemplateInstance* inst; + ScopeDsymbol* argsym; + size_t hash; + Array* fargs; + Array* deferred; + Module* memberOf; + TemplateInstance* tinst; + TemplateInstance* tnext; + Module* minst; +private: + uint16_t _nest; +public: + uint8_t inuse; +private: + enum class Flag : uint32_t + { + semantictiargsdone = 32768u, + havetempdecl = 16384u, + gagged = 8192u, + available = 8191u, + }; + +public: + TemplateInstance* syntaxCopy(Dsymbol* s) override; + Dsymbol* toAlias() final override; + const char* kind() const override; + bool oneMember(Dsymbol** ps, Identifier* ident) override; + const char* toChars() const override; + const char* toPrettyCharsHelper() final override; + Identifier* getIdent() final override; + bool equalsx(TemplateInstance* ti); + bool isDiscardable(); + bool needsCodegen(); + TemplateInstance* isTemplateInstance() final override; + void accept(Visitor* v) override; +}; + +struct TemplateInstanceBox final +{ + TemplateInstance* ti; + TemplateInstanceBox() : + ti() + { + } +}; + +class TemplateMixin final : public TemplateInstance +{ +public: + TypeQualified* tqual; + TemplateInstance* syntaxCopy(Dsymbol* s) override; + const char* kind() const override; + bool oneMember(Dsymbol** ps, Identifier* ident) override; + bool hasPointers() override; + void setFieldOffset(AggregateDeclaration* ad, FieldState& fieldState, bool isunion) override; + const char* toChars() const override; + TemplateMixin* isTemplateMixin() override; + void accept(Visitor* v) override; +}; + +struct TemplatePrevious final +{ + TemplatePrevious* prev; + Scope* sc; + Array* dedargs; + TemplatePrevious() : + prev(), + sc(), + dedargs() + { + } + TemplatePrevious(TemplatePrevious* prev, Scope* sc = nullptr, Array* dedargs = nullptr) : + prev(prev), + sc(sc), + dedargs(dedargs) + {} +}; + +struct TemplateStats final +{ + uint32_t numInstantiations; + uint32_t uniqueInstantiations; + Array* allInstances; + TemplateStats() : + numInstantiations(), + uniqueInstantiations(), + allInstances() + { + } + TemplateStats(uint32_t numInstantiations, uint32_t uniqueInstantiations = 0u, Array* allInstances = nullptr) : + numInstantiations(numInstantiations), + uniqueInstantiations(uniqueInstantiations), + allInstances(allInstances) + {} +}; + +class TemplateTypeParameter : public TemplateParameter +{ +public: + Type* specType; + Type* defaultType; + TemplateTypeParameter* isTemplateTypeParameter() final override; + TemplateTypeParameter* syntaxCopy() override; + bool declareParameter(Scope* sc) final override; + void print(RootObject* oarg, RootObject* oded) final override; + RootObject* specialization() final override; + RootObject* defaultArg(const Loc& instLoc, Scope* sc) final override; + bool hasDefaultArg() final override; + RootObject* dummyArg() final override; + void accept(Visitor* v) override; +}; + +class TemplateThisParameter final : public TemplateTypeParameter +{ +public: + TemplateThisParameter* isTemplateThisParameter() override; + TemplateThisParameter* syntaxCopy() override; + void accept(Visitor* v) override; +}; + +class TemplateTupleParameter final : public TemplateParameter +{ +public: + TemplateTupleParameter* isTemplateTupleParameter() override; + TemplateTupleParameter* syntaxCopy() override; + bool declareParameter(Scope* sc) override; + void print(RootObject* oarg, RootObject* oded) override; + RootObject* specialization() override; + RootObject* defaultArg(const Loc& instLoc, Scope* sc) override; + bool hasDefaultArg() override; + RootObject* dummyArg() override; + void accept(Visitor* v) override; +}; + +class TemplateValueParameter final : public TemplateParameter +{ +public: + Type* valType; + Expression* specValue; + Expression* defaultValue; + TemplateValueParameter* isTemplateValueParameter() override; + TemplateValueParameter* syntaxCopy() override; + bool declareParameter(Scope* sc) override; + void print(RootObject* oarg, RootObject* oded) override; + RootObject* specialization() override; + RootObject* defaultArg(const Loc& instLoc, Scope* sc) override; + bool hasDefaultArg() override; + RootObject* dummyArg() override; + void accept(Visitor* v) override; +}; + +class Tuple final : public RootObject +{ +public: + Array objects; + DYNCAST dyncast() const override; + const char* toChars() const override; +}; + +enum class TY : uint8_t +{ + Tarray = 0u, + Tsarray = 1u, + Taarray = 2u, + Tpointer = 3u, + Treference = 4u, + Tfunction = 5u, + Tident = 6u, + Tclass = 7u, + Tstruct = 8u, + Tenum = 9u, + Tdelegate = 10u, + Tnone = 11u, + Tvoid = 12u, + Tint8 = 13u, + Tuns8 = 14u, + Tint16 = 15u, + Tuns16 = 16u, + Tint32 = 17u, + Tuns32 = 18u, + Tint64 = 19u, + Tuns64 = 20u, + Tfloat32 = 21u, + Tfloat64 = 22u, + Tfloat80 = 23u, + Timaginary32 = 24u, + Timaginary64 = 25u, + Timaginary80 = 26u, + Tcomplex32 = 27u, + Tcomplex64 = 28u, + Tcomplex80 = 29u, + Tbool = 30u, + Tchar = 31u, + Twchar = 32u, + Tdchar = 33u, + Terror = 34u, + Tinstance = 35u, + Ttypeof = 36u, + Ttuple = 37u, + Tslice = 38u, + Treturn = 39u, + Tnull = 40u, + Tvector = 41u, + Tint128 = 42u, + Tuns128 = 43u, + Ttraits = 44u, + Tmixin = 45u, + Tnoreturn = 46u, + Ttag = 47u, +}; + +enum class Covariant +{ + distinct = 0, + yes = 1, + no = 2, + fwdref = 3, +}; + +typedef uint64_t dinteger_t; + +class Type : public ASTNode +{ +public: + TY ty; + uint8_t mod; + char* deco; + struct Mcache final + { + Type* cto; + Type* ito; + Type* sto; + Type* scto; + Type* wto; + Type* wcto; + Type* swto; + Type* swcto; + Mcache() : + cto(), + ito(), + sto(), + scto(), + wto(), + wcto(), + swto(), + swcto() + { + } + Mcache(Type* cto, Type* ito = nullptr, Type* sto = nullptr, Type* scto = nullptr, Type* wto = nullptr, Type* wcto = nullptr, Type* swto = nullptr, Type* swcto = nullptr) : + cto(cto), + ito(ito), + sto(sto), + scto(scto), + wto(wto), + wcto(wcto), + swto(swto), + swcto(swcto) + {} + }; + +private: + Mcache* mcache; +public: + Type* pto; + Type* rto; + Type* arrayof; + TypeInfoDeclaration* vtinfo; + TYPE* ctype; + static Type* tvoid; + static Type* tint8; + static Type* tuns8; + static Type* tint16; + static Type* tuns16; + static Type* tint32; + static Type* tuns32; + static Type* tint64; + static Type* tuns64; + static Type* tint128; + static Type* tuns128; + static Type* tfloat32; + static Type* tfloat64; + static Type* tfloat80; + static Type* timaginary32; + static Type* timaginary64; + static Type* timaginary80; + static Type* tcomplex32; + static Type* tcomplex64; + static Type* tcomplex80; + static Type* tbool; + static Type* tchar; + static Type* twchar; + static Type* tdchar; + static Type* tshiftcnt; + static Type* tvoidptr; + static Type* tstring; + static Type* twstring; + static Type* tdstring; + static Type* terror; + static Type* tnull; + static Type* tnoreturn; + static Type* tsize_t; + static Type* tptrdiff_t; + static Type* thash_t; + static ClassDeclaration* dtypeinfo; + static ClassDeclaration* typeinfoclass; + static ClassDeclaration* typeinfointerface; + static ClassDeclaration* typeinfostruct; + static ClassDeclaration* typeinfopointer; + static ClassDeclaration* typeinfoarray; + static ClassDeclaration* typeinfostaticarray; + static ClassDeclaration* typeinfoassociativearray; + static ClassDeclaration* typeinfovector; + static ClassDeclaration* typeinfoenum; + static ClassDeclaration* typeinfofunction; + static ClassDeclaration* typeinfodelegate; + static ClassDeclaration* typeinfotypelist; + static ClassDeclaration* typeinfoconst; + static ClassDeclaration* typeinfoinvariant; + static ClassDeclaration* typeinfoshared; + static ClassDeclaration* typeinfowild; + static TemplateDeclaration* rtinfo; + static Type* basic[48LLU]; + virtual const char* kind() const; + Type* copy() const; + virtual Type* syntaxCopy(); + bool equals(const RootObject* const o) const override; + bool equivalent(Type* t); + DYNCAST dyncast() const final override; + size_t getUniqueID() const; + Covariant covariant(Type* t, uint64_t* pstc = nullptr, bool cppCovariant = false); + const char* toChars() const final override; + char* toPrettyChars(bool QualifyTypes = false); + static void _init(); + static void deinitialize(); + uinteger_t size(); + virtual uinteger_t size(const Loc& loc); + virtual uint32_t alignsize(); + Type* trySemantic(const Loc& loc, Scope* sc); + Type* merge2(); + void modToBuffer(OutBuffer& buf) const; + char* modToChars() const; + virtual bool isintegral(); + virtual bool isfloating(); + virtual bool isreal(); + virtual bool isimaginary(); + virtual bool iscomplex(); + virtual bool isscalar(); + virtual bool isunsigned(); + virtual bool isscope(); + virtual bool isString(); + virtual bool isAssignable(); + virtual bool isBoolean(); + virtual void checkDeprecated(const Loc& loc, Scope* sc); + bool isConst() const; + bool isImmutable() const; + bool isMutable() const; + bool isShared() const; + bool isSharedConst() const; + bool isWild() const; + bool isWildConst() const; + bool isSharedWild() const; + bool isNaked() const; + Type* nullAttributes() const; + Type* constOf(); + Type* immutableOf(); + Type* mutableOf(); + Type* sharedOf(); + Type* sharedConstOf(); + Type* unSharedOf(); + Type* wildOf(); + Type* wildConstOf(); + Type* sharedWildOf(); + Type* sharedWildConstOf(); + Type* castMod(uint8_t mod); + Type* addMod(uint8_t mod); + virtual Type* addStorageClass(StorageClass stc); + Type* pointerTo(); + Type* referenceTo(); + Type* arrayOf(); + Type* sarrayOf(dinteger_t dim); + bool hasDeprecatedAliasThis(); + Type* aliasthisOf(); + virtual Type* makeConst(); + virtual Type* makeImmutable(); + virtual Type* makeShared(); + virtual Type* makeSharedConst(); + virtual Type* makeWild(); + virtual Type* makeWildConst(); + virtual Type* makeSharedWild(); + virtual Type* makeSharedWildConst(); + virtual Type* makeMutable(); + virtual Dsymbol* toDsymbol(Scope* sc); + Type* toBasetype(); + virtual bool isBaseOf(Type* t, int32_t* poffset); + virtual MATCH implicitConvTo(Type* to); + virtual MATCH constConv(Type* to); + virtual uint8_t deduceWild(Type* t, bool isRef); + virtual Type* substWildTo(uint32_t mod); + Type* unqualify(uint32_t m); + virtual Type* toHeadMutable(); + virtual ClassDeclaration* isClassHandle(); + virtual structalign_t alignment(); + virtual Expression* defaultInitLiteral(const Loc& loc); + virtual bool isZeroInit(const Loc& loc); + Identifier* getTypeInfoIdent(); + virtual int32_t hasWild() const; + virtual bool hasPointers(); + virtual bool hasVoidInitPointers(); + virtual bool hasSystemFields(); + virtual bool hasInvariant(); + virtual Type* nextOf(); + Type* baseElemOf(); + uint32_t numberOfElems(const Loc& loc); + virtual bool needsDestruction(); + virtual bool needsCopyOrPostblit(); + virtual bool needsNested(); + virtual TypeBasic* isTypeBasic(); + TypeFunction* isPtrToFunction(); + TypeFunction* isFunction_Delegate_PtrToFunction(); + TypeError* isTypeError(); + TypeVector* isTypeVector(); + TypeSArray* isTypeSArray(); + TypeDArray* isTypeDArray(); + TypeAArray* isTypeAArray(); + TypePointer* isTypePointer(); + TypeReference* isTypeReference(); + TypeFunction* isTypeFunction(); + TypeDelegate* isTypeDelegate(); + TypeIdentifier* isTypeIdentifier(); + TypeInstance* isTypeInstance(); + TypeTypeof* isTypeTypeof(); + TypeReturn* isTypeReturn(); + TypeStruct* isTypeStruct(); + TypeEnum* isTypeEnum(); + TypeClass* isTypeClass(); + TypeTuple* isTypeTuple(); + TypeSlice* isTypeSlice(); + TypeNull* isTypeNull(); + TypeMixin* isTypeMixin(); + TypeTraits* isTypeTraits(); + TypeNoreturn* isTypeNoreturn(); + TypeTag* isTypeTag(); + void accept(Visitor* v) override; + TypeFunction* toTypeFunction(); +}; + +class TypeDeduced final : public Type +{ +public: + Type* tded; + Array argexps; + Array tparams; + void update(Expression* e, Type* tparam); + void update(Type* tt, Expression* e, Type* tparam); + MATCH matchAll(Type* tt); +}; + +extern Dsymbol* isDsymbol(RootObject* o); + +extern bool isError(const RootObject* const o); + +extern Expression* isExpression(RootObject* o); + +extern Parameter* isParameter(RootObject* o); + +extern TemplateParameter* isTemplateParameter(RootObject* o); + +extern Tuple* isTuple(RootObject* o); + +extern Type* isType(RootObject* o); + +extern void printTemplateStats(); + +class DebugSymbol final : public Dsymbol +{ +public: + uint32_t level; + DebugSymbol* syntaxCopy(Dsymbol* s) override; + const char* toChars() const override; + const char* kind() const override; + DebugSymbol* isDebugSymbol() override; + void accept(Visitor* v) override; +}; + +class VersionSymbol final : public Dsymbol +{ +public: + uint32_t level; + VersionSymbol* syntaxCopy(Dsymbol* s) override; + const char* toChars() const override; + const char* kind() const override; + VersionSymbol* isVersionSymbol() override; + void accept(Visitor* v) override; +}; + +enum class EXP : uint8_t +{ + reserved = 0u, + negate = 1u, + cast_ = 2u, + null_ = 3u, + assert_ = 4u, + array = 5u, + call = 6u, + address = 7u, + type = 8u, + throw_ = 9u, + new_ = 10u, + delete_ = 11u, + star = 12u, + symbolOffset = 13u, + variable = 14u, + dotVariable = 15u, + dotIdentifier = 16u, + dotTemplateInstance = 17u, + dotType = 18u, + slice = 19u, + arrayLength = 20u, + dollar = 21u, + template_ = 22u, + dotTemplateDeclaration = 23u, + declaration = 24u, + dSymbol = 25u, + typeid_ = 26u, + uadd = 27u, + remove = 28u, + newAnonymousClass = 29u, + arrayLiteral = 30u, + assocArrayLiteral = 31u, + structLiteral = 32u, + classReference = 33u, + thrownException = 34u, + delegatePointer = 35u, + delegateFunctionPointer = 36u, + lessThan = 37u, + greaterThan = 38u, + lessOrEqual = 39u, + greaterOrEqual = 40u, + equal = 41u, + notEqual = 42u, + identity = 43u, + notIdentity = 44u, + index = 45u, + is_ = 46u, + leftShift = 47u, + rightShift = 48u, + leftShiftAssign = 49u, + rightShiftAssign = 50u, + unsignedRightShift = 51u, + unsignedRightShiftAssign = 52u, + concatenate = 53u, + concatenateAssign = 54u, + concatenateElemAssign = 55u, + concatenateDcharAssign = 56u, + add = 57u, + min = 58u, + addAssign = 59u, + minAssign = 60u, + mul = 61u, + div = 62u, + mod = 63u, + mulAssign = 64u, + divAssign = 65u, + modAssign = 66u, + and_ = 67u, + or_ = 68u, + xor_ = 69u, + andAssign = 70u, + orAssign = 71u, + xorAssign = 72u, + assign = 73u, + not_ = 74u, + tilde = 75u, + plusPlus = 76u, + minusMinus = 77u, + construct = 78u, + blit = 79u, + dot = 80u, + comma = 81u, + question = 82u, + andAnd = 83u, + orOr = 84u, + prePlusPlus = 85u, + preMinusMinus = 86u, + identifier = 87u, + string_ = 88u, + this_ = 89u, + super_ = 90u, + halt = 91u, + tuple = 92u, + error = 93u, + void_ = 94u, + int64 = 95u, + float64 = 96u, + complex80 = 97u, + import_ = 98u, + delegate_ = 99u, + function_ = 100u, + mixin_ = 101u, + in_ = 102u, + break_ = 103u, + continue_ = 104u, + goto_ = 105u, + scope_ = 106u, + traits = 107u, + overloadSet = 108u, + line = 109u, + file = 110u, + fileFullPath = 111u, + moduleString = 112u, + functionString = 113u, + prettyFunction = 114u, + pow = 115u, + powAssign = 116u, + vector = 117u, + voidExpression = 118u, + cantExpression = 119u, + showCtfeContext = 120u, + objcClassReference = 121u, + vectorArray = 122u, + compoundLiteral = 123u, + _Generic_ = 124u, + interval = 125u, + loweredAssignExp = 126u, +}; + +struct complex_t final +{ + _d_real re; + _d_real im; + complex_t() = delete; + complex_t(_d_real re); + complex_t(_d_real re, _d_real im); + int32_t opEquals(complex_t y) const; +}; + +template +struct Optional final +{ + T value; + bool present; + Optional(T value); + static Optional create(T val); + bool isPresent() const; + bool isEmpty() const; + T get(); + bool hasValue(T exp) const; + Optional() + { + } +}; + +class Expression : public ASTNode +{ +public: + Type* type; + Loc loc; + const EXP op; + size_t size() const; + static void _init(); + static void deinitialize(); + virtual Expression* syntaxCopy(); + DYNCAST dyncast() const final override; + const char* toChars() const override; + virtual dinteger_t toInteger(); + virtual uinteger_t toUInteger(); + virtual _d_real toReal(); + virtual _d_real toImaginary(); + virtual complex_t toComplex(); + virtual StringExp* toStringExp(); + virtual bool isLvalue(); + virtual bool checkType(); + virtual bool checkValue(); + Expression* addressOf(); + Expression* deref(); + int32_t isConst(); + virtual bool isIdentical(const Expression* const e) const; + virtual Optional toBool(); + virtual bool hasCode(); + IntegerExp* isIntegerExp(); + ErrorExp* isErrorExp(); + VoidInitExp* isVoidInitExp(); + RealExp* isRealExp(); + ComplexExp* isComplexExp(); + IdentifierExp* isIdentifierExp(); + DollarExp* isDollarExp(); + DsymbolExp* isDsymbolExp(); + ThisExp* isThisExp(); + SuperExp* isSuperExp(); + NullExp* isNullExp(); + StringExp* isStringExp(); + TupleExp* isTupleExp(); + ArrayLiteralExp* isArrayLiteralExp(); + AssocArrayLiteralExp* isAssocArrayLiteralExp(); + StructLiteralExp* isStructLiteralExp(); + CompoundLiteralExp* isCompoundLiteralExp(); + TypeExp* isTypeExp(); + ScopeExp* isScopeExp(); + TemplateExp* isTemplateExp(); + NewExp* isNewExp(); + NewAnonClassExp* isNewAnonClassExp(); + SymOffExp* isSymOffExp(); + VarExp* isVarExp(); + OverExp* isOverExp(); + FuncExp* isFuncExp(); + DeclarationExp* isDeclarationExp(); + TypeidExp* isTypeidExp(); + TraitsExp* isTraitsExp(); + HaltExp* isHaltExp(); + IsExp* isExp(); + MixinExp* isMixinExp(); + ImportExp* isImportExp(); + AssertExp* isAssertExp(); + ThrowExp* isThrowExp(); + DotIdExp* isDotIdExp(); + DotTemplateExp* isDotTemplateExp(); + DotVarExp* isDotVarExp(); + DotTemplateInstanceExp* isDotTemplateInstanceExp(); + DelegateExp* isDelegateExp(); + DotTypeExp* isDotTypeExp(); + CallExp* isCallExp(); + AddrExp* isAddrExp(); + PtrExp* isPtrExp(); + NegExp* isNegExp(); + UAddExp* isUAddExp(); + ComExp* isComExp(); + NotExp* isNotExp(); + DeleteExp* isDeleteExp(); + CastExp* isCastExp(); + VectorExp* isVectorExp(); + VectorArrayExp* isVectorArrayExp(); + SliceExp* isSliceExp(); + ArrayLengthExp* isArrayLengthExp(); + ArrayExp* isArrayExp(); + DotExp* isDotExp(); + CommaExp* isCommaExp(); + IntervalExp* isIntervalExp(); + DelegatePtrExp* isDelegatePtrExp(); + DelegateFuncptrExp* isDelegateFuncptrExp(); + IndexExp* isIndexExp(); + PostExp* isPostExp(); + PreExp* isPreExp(); + AssignExp* isAssignExp(); + LoweredAssignExp* isLoweredAssignExp(); + ConstructExp* isConstructExp(); + BlitExp* isBlitExp(); + AddAssignExp* isAddAssignExp(); + MinAssignExp* isMinAssignExp(); + MulAssignExp* isMulAssignExp(); + DivAssignExp* isDivAssignExp(); + ModAssignExp* isModAssignExp(); + AndAssignExp* isAndAssignExp(); + OrAssignExp* isOrAssignExp(); + XorAssignExp* isXorAssignExp(); + PowAssignExp* isPowAssignExp(); + ShlAssignExp* isShlAssignExp(); + ShrAssignExp* isShrAssignExp(); + UshrAssignExp* isUshrAssignExp(); + CatAssignExp* isCatAssignExp(); + CatElemAssignExp* isCatElemAssignExp(); + CatDcharAssignExp* isCatDcharAssignExp(); + AddExp* isAddExp(); + MinExp* isMinExp(); + CatExp* isCatExp(); + MulExp* isMulExp(); + DivExp* isDivExp(); + ModExp* isModExp(); + PowExp* isPowExp(); + ShlExp* isShlExp(); + ShrExp* isShrExp(); + UshrExp* isUshrExp(); + AndExp* isAndExp(); + OrExp* isOrExp(); + XorExp* isXorExp(); + LogicalExp* isLogicalExp(); + InExp* isInExp(); + RemoveExp* isRemoveExp(); + EqualExp* isEqualExp(); + IdentityExp* isIdentityExp(); + CondExp* isCondExp(); + GenericExp* isGenericExp(); + DefaultInitExp* isDefaultInitExp(); + FileInitExp* isFileInitExp(); + LineInitExp* isLineInitExp(); + ModuleInitExp* isModuleInitExp(); + FuncInitExp* isFuncInitExp(); + PrettyFuncInitExp* isPrettyFuncInitExp(); + ObjcClassReferenceExp* isObjcClassReferenceExp(); + ClassReferenceExp* isClassReferenceExp(); + ThrownExceptionExp* isThrownExceptionExp(); + UnaExp* isUnaExp(); + BinExp* isBinExp(); + BinAssignExp* isBinAssignExp(); + void accept(Visitor* v) override; +}; + +class BinExp : public Expression +{ +public: + Expression* e1; + Expression* e2; + Type* att1; + Type* att2; + BinExp* syntaxCopy() override; + void setNoderefOperands(); + void accept(Visitor* v) override; +}; + +class BinAssignExp : public BinExp +{ +public: + bool isLvalue() final override; + void accept(Visitor* v) override; +}; + +class AddAssignExp final : public BinAssignExp +{ +public: + void accept(Visitor* v) override; +}; + +class AddExp final : public BinExp +{ +public: + void accept(Visitor* v) override; +}; + +class UnaExp : public Expression +{ +public: + Expression* e1; + UnaExp* syntaxCopy() override; + void setNoderefOperand(); + void accept(Visitor* v) override; +}; + +class AddrExp final : public UnaExp +{ +public: + void accept(Visitor* v) override; +}; + +class AndAssignExp final : public BinAssignExp +{ +public: + void accept(Visitor* v) override; +}; + +class AndExp final : public BinExp +{ +public: + void accept(Visitor* v) override; +}; + +struct ArgumentList final +{ + Array* arguments; + Array* names; + ArgumentList() : + arguments(), + names() + { + } + ArgumentList(Array* arguments, Array* names = nullptr) : + arguments(arguments), + names(names) + {} +}; + +class ArrayExp final : public UnaExp +{ +public: + Array* arguments; + size_t currentDimension; + VarDeclaration* lengthVar; + ArrayExp* syntaxCopy() override; + bool isLvalue() override; + void accept(Visitor* v) override; +}; + +class ArrayLengthExp final : public UnaExp +{ +public: + void accept(Visitor* v) override; +}; + +enum class OwnedBy : uint8_t +{ + code = 0u, + ctfe = 1u, + cache = 2u, +}; + +class ArrayLiteralExp final : public Expression +{ +public: + OwnedBy ownedByCtfe; + bool onstack; + Expression* basis; + Array* elements; + static ArrayLiteralExp* create(const Loc& loc, Array* elements); + ArrayLiteralExp* syntaxCopy() override; + bool equals(const RootObject* const o) const override; + Expression* getElement(size_t i); + Optional toBool() override; + StringExp* toStringExp() override; + void accept(Visitor* v) override; +}; + +class AssertExp final : public UnaExp +{ +public: + Expression* msg; + AssertExp* syntaxCopy() override; + void accept(Visitor* v) override; +}; + +enum class MemorySet +{ + none = 0, + blockAssign = 1, + referenceInit = 2, +}; + +class AssignExp : public BinExp +{ +public: + MemorySet memset; + AssignExp(const Loc& loc, EXP tok, Expression* e1, Expression* e2); + bool isLvalue() final override; + void accept(Visitor* v) override; +}; + +class AssocArrayLiteralExp final : public Expression +{ +public: + OwnedBy ownedByCtfe; + Array* keys; + Array* values; + Expression* lowering; + bool equals(const RootObject* const o) const override; + AssocArrayLiteralExp* syntaxCopy() override; + Optional toBool() override; + void accept(Visitor* v) override; +}; + +class BlitExp final : public AssignExp +{ +public: + void accept(Visitor* v) override; +}; + +class CTFEExp final : public Expression +{ +public: + const char* toChars() const override; +}; + +class CallExp final : public UnaExp +{ +public: + Array* arguments; + Array* names; + FuncDeclaration* f; + bool directcall; + bool inDebugStatement; + bool ignoreAttributes; + bool isUfcsRewrite; + VarDeclaration* vthis2; + static CallExp* create(const Loc& loc, Expression* e, Array* exps); + static CallExp* create(const Loc& loc, Expression* e); + static CallExp* create(const Loc& loc, Expression* e, Expression* earg1); + static CallExp* create(const Loc& loc, FuncDeclaration* fd, Expression* earg1); + CallExp* syntaxCopy() override; + bool isLvalue() override; + void accept(Visitor* v) override; +}; + +class CastExp final : public UnaExp +{ +public: + Type* to; + uint8_t mod; + CastExp* syntaxCopy() override; + bool isLvalue() override; + void accept(Visitor* v) override; +}; + +class CatAssignExp : public BinAssignExp +{ +public: + Expression* lowering; + void accept(Visitor* v) override; +}; + +class CatDcharAssignExp final : public CatAssignExp +{ +public: + void accept(Visitor* v) override; +}; + +class CatElemAssignExp final : public CatAssignExp +{ +public: + void accept(Visitor* v) override; +}; + +class CatExp final : public BinExp +{ +public: + Expression* lowering; + void accept(Visitor* v) override; +}; + +class ClassReferenceExp final : public Expression +{ +public: + StructLiteralExp* value; + ClassDeclaration* originalClass(); + int32_t getFieldIndex(Type* fieldtype, uint32_t fieldoffset); + int32_t findFieldIndexByName(VarDeclaration* v); + void accept(Visitor* v) override; +}; + +class CmpExp final : public BinExp +{ +public: + void accept(Visitor* v) override; +}; + +class ComExp final : public UnaExp +{ +public: + void accept(Visitor* v) override; +}; + +class CommaExp final : public BinExp +{ +public: + const bool isGenerated; + bool allowCommaExp; + bool isLvalue() override; + Optional toBool() override; + void accept(Visitor* v) override; + static void allow(Expression* exp); +}; + +class ComplexExp final : public Expression +{ +public: + complex_t value; + static ComplexExp* create(const Loc& loc, complex_t value, Type* type); + bool equals(const RootObject* const o) const override; + bool isIdentical(const Expression* const e) const override; + dinteger_t toInteger() override; + uinteger_t toUInteger() override; + _d_real toReal() override; + _d_real toImaginary() override; + complex_t toComplex() override; + Optional toBool() override; + void accept(Visitor* v) override; +}; + +class CompoundLiteralExp final : public Expression +{ +public: + Initializer* initializer; + void accept(Visitor* v) override; +}; + +class CondExp final : public BinExp +{ +public: + Expression* econd; + CondExp* syntaxCopy() override; + bool isLvalue() override; + void accept(Visitor* v) override; +}; + +class ConstructExp final : public AssignExp +{ +public: + void accept(Visitor* v) override; +}; + +class DeclarationExp final : public Expression +{ +public: + Dsymbol* declaration; + DeclarationExp* syntaxCopy() override; + bool hasCode() override; + void accept(Visitor* v) override; +}; + +class DefaultInitExp : public Expression +{ +public: + void accept(Visitor* v) override; +}; + +class DelegateExp final : public UnaExp +{ +public: + FuncDeclaration* func; + bool hasOverloads; + VarDeclaration* vthis2; + void accept(Visitor* v) override; +}; + +class DelegateFuncptrExp final : public UnaExp +{ +public: + bool isLvalue() override; + void accept(Visitor* v) override; +}; + +class DelegatePtrExp final : public UnaExp +{ +public: + bool isLvalue() override; + void accept(Visitor* v) override; +}; + +class DeleteExp final : public UnaExp +{ +public: + bool isRAII; + void accept(Visitor* v) override; +}; + +class DivAssignExp final : public BinAssignExp +{ +public: + void accept(Visitor* v) override; +}; + +class DivExp final : public BinExp +{ +public: + void accept(Visitor* v) override; +}; + +class IdentifierExp : public Expression +{ +public: + Identifier* ident; + bool parens; + static IdentifierExp* create(const Loc& loc, Identifier* ident); + bool isLvalue() final override; + void accept(Visitor* v) override; +}; + +class DollarExp final : public IdentifierExp +{ +public: + void accept(Visitor* v) override; +}; + +class DotExp final : public BinExp +{ +public: + void accept(Visitor* v) override; +}; + +class DotIdExp final : public UnaExp +{ +public: + Identifier* ident; + bool noderef; + bool wantsym; + bool arrow; + static DotIdExp* create(const Loc& loc, Expression* e, Identifier* ident); + void accept(Visitor* v) override; +}; + +class DotTemplateExp final : public UnaExp +{ +public: + TemplateDeclaration* td; + bool checkType() override; + bool checkValue() override; + void accept(Visitor* v) override; +}; + +class DotTemplateInstanceExp final : public UnaExp +{ +public: + TemplateInstance* ti; + DotTemplateInstanceExp* syntaxCopy() override; + bool checkType() override; + bool checkValue() override; + void accept(Visitor* v) override; +}; + +class DotTypeExp final : public UnaExp +{ +public: + Dsymbol* sym; + void accept(Visitor* v) override; +}; + +class DotVarExp final : public UnaExp +{ +public: + Declaration* var; + bool hasOverloads; + bool isLvalue() override; + void accept(Visitor* v) override; +}; + +class DsymbolExp final : public Expression +{ +public: + Dsymbol* s; + bool hasOverloads; + bool isLvalue() override; + void accept(Visitor* v) override; +}; + +class EqualExp final : public BinExp +{ +public: + void accept(Visitor* v) override; +}; + +class ErrorExp final : public Expression +{ +public: + static ErrorExp* get(); + void accept(Visitor* v) override; + static ErrorExp* errorexp; +}; + +class FileInitExp final : public DefaultInitExp +{ +public: + void accept(Visitor* v) override; +}; + +enum class TOK : uint8_t +{ + reserved = 0u, + leftParenthesis = 1u, + rightParenthesis = 2u, + leftBracket = 3u, + rightBracket = 4u, + leftCurly = 5u, + rightCurly = 6u, + colon = 7u, + semicolon = 8u, + dotDotDot = 9u, + endOfFile = 10u, + cast_ = 11u, + null_ = 12u, + assert_ = 13u, + true_ = 14u, + false_ = 15u, + throw_ = 16u, + new_ = 17u, + delete_ = 18u, + variable = 19u, + slice = 20u, + version_ = 21u, + module_ = 22u, + dollar = 23u, + template_ = 24u, + typeof_ = 25u, + pragma_ = 26u, + typeid_ = 27u, + comment = 28u, + lessThan = 29u, + greaterThan = 30u, + lessOrEqual = 31u, + greaterOrEqual = 32u, + equal = 33u, + notEqual = 34u, + identity = 35u, + notIdentity = 36u, + is_ = 37u, + leftShift = 38u, + rightShift = 39u, + leftShiftAssign = 40u, + rightShiftAssign = 41u, + unsignedRightShift = 42u, + unsignedRightShiftAssign = 43u, + concatenateAssign = 44u, + add = 45u, + min = 46u, + addAssign = 47u, + minAssign = 48u, + mul = 49u, + div = 50u, + mod = 51u, + mulAssign = 52u, + divAssign = 53u, + modAssign = 54u, + and_ = 55u, + or_ = 56u, + xor_ = 57u, + andAssign = 58u, + orAssign = 59u, + xorAssign = 60u, + assign = 61u, + not_ = 62u, + tilde = 63u, + plusPlus = 64u, + minusMinus = 65u, + dot = 66u, + comma = 67u, + question = 68u, + andAnd = 69u, + orOr = 70u, + int32Literal = 71u, + uns32Literal = 72u, + int64Literal = 73u, + uns64Literal = 74u, + int128Literal = 75u, + uns128Literal = 76u, + float32Literal = 77u, + float64Literal = 78u, + float80Literal = 79u, + imaginary32Literal = 80u, + imaginary64Literal = 81u, + imaginary80Literal = 82u, + charLiteral = 83u, + wcharLiteral = 84u, + dcharLiteral = 85u, + identifier = 86u, + string_ = 87u, + hexadecimalString = 88u, + this_ = 89u, + super_ = 90u, + error = 91u, + void_ = 92u, + int8 = 93u, + uns8 = 94u, + int16 = 95u, + uns16 = 96u, + int32 = 97u, + uns32 = 98u, + int64 = 99u, + uns64 = 100u, + int128 = 101u, + uns128 = 102u, + float32 = 103u, + float64 = 104u, + float80 = 105u, + imaginary32 = 106u, + imaginary64 = 107u, + imaginary80 = 108u, + complex32 = 109u, + complex64 = 110u, + complex80 = 111u, + char_ = 112u, + wchar_ = 113u, + dchar_ = 114u, + bool_ = 115u, + struct_ = 116u, + class_ = 117u, + interface_ = 118u, + union_ = 119u, + enum_ = 120u, + import_ = 121u, + alias_ = 122u, + override_ = 123u, + delegate_ = 124u, + function_ = 125u, + mixin_ = 126u, + align_ = 127u, + extern_ = 128u, + private_ = 129u, + protected_ = 130u, + public_ = 131u, + export_ = 132u, + static_ = 133u, + final_ = 134u, + const_ = 135u, + abstract_ = 136u, + debug_ = 137u, + deprecated_ = 138u, + in_ = 139u, + out_ = 140u, + inout_ = 141u, + lazy_ = 142u, + auto_ = 143u, + package_ = 144u, + immutable_ = 145u, + if_ = 146u, + else_ = 147u, + while_ = 148u, + for_ = 149u, + do_ = 150u, + switch_ = 151u, + case_ = 152u, + default_ = 153u, + break_ = 154u, + continue_ = 155u, + with_ = 156u, + synchronized_ = 157u, + return_ = 158u, + goto_ = 159u, + try_ = 160u, + catch_ = 161u, + finally_ = 162u, + asm_ = 163u, + foreach_ = 164u, + foreach_reverse_ = 165u, + scope_ = 166u, + onScopeExit = 167u, + onScopeFailure = 168u, + onScopeSuccess = 169u, + invariant_ = 170u, + unittest_ = 171u, + argumentTypes = 172u, + ref_ = 173u, + macro_ = 174u, + parameters = 175u, + traits = 176u, + pure_ = 177u, + nothrow_ = 178u, + gshared = 179u, + line = 180u, + file = 181u, + fileFullPath = 182u, + moduleString = 183u, + functionString = 184u, + prettyFunction = 185u, + shared_ = 186u, + at = 187u, + pow = 188u, + powAssign = 189u, + goesTo = 190u, + vector = 191u, + pound = 192u, + arrow = 193u, + colonColon = 194u, + wchar_tLiteral = 195u, + endOfLine = 196u, + whitespace = 197u, + inline_ = 198u, + register_ = 199u, + restrict_ = 200u, + signed_ = 201u, + sizeof_ = 202u, + typedef_ = 203u, + unsigned_ = 204u, + volatile_ = 205u, + _Alignas_ = 206u, + _Alignof_ = 207u, + _Atomic_ = 208u, + _Bool_ = 209u, + _Complex_ = 210u, + _Generic_ = 211u, + _Imaginary_ = 212u, + _Noreturn_ = 213u, + _Static_assert_ = 214u, + _Thread_local_ = 215u, + _assert_ = 216u, + _import_ = 217u, + __cdecl_ = 218u, + __declspec_ = 219u, + __stdcall_ = 220u, + __thread_ = 221u, + __pragma_ = 222u, + __int128_ = 223u, + __attribute___ = 224u, +}; + +class FuncExp final : public Expression +{ +public: + FuncLiteralDeclaration* fd; + TemplateDeclaration* td; + TOK tok; + bool equals(const RootObject* const o) const override; + FuncExp* syntaxCopy() override; + const char* toChars() const override; + bool checkType() override; + bool checkValue() override; + void accept(Visitor* v) override; +}; + +class FuncInitExp final : public DefaultInitExp +{ +public: + void accept(Visitor* v) override; +}; + +class GenericExp final : public Expression +{ +public: + Expression* cntlExp; + Array* types; + Array* exps; + GenericExp* syntaxCopy() override; + void accept(Visitor* v) override; +}; + +class HaltExp final : public Expression +{ +public: + void accept(Visitor* v) override; +}; + +class IdentityExp final : public BinExp +{ +public: + void accept(Visitor* v) override; +}; + +class ImportExp final : public UnaExp +{ +public: + void accept(Visitor* v) override; +}; + +class InExp final : public BinExp +{ +public: + void accept(Visitor* v) override; +}; + +class IndexExp final : public BinExp +{ +public: + VarDeclaration* lengthVar; + bool modifiable; + bool indexIsInBounds; + IndexExp* syntaxCopy() override; + bool isLvalue() override; + void accept(Visitor* v) override; +}; + +class IntegerExp final : public Expression +{ + dinteger_t value; +public: + static IntegerExp* create(const Loc& loc, dinteger_t value, Type* type); + bool equals(const RootObject* const o) const override; + dinteger_t toInteger() override; + _d_real toReal() override; + _d_real toImaginary() override; + complex_t toComplex() override; + Optional toBool() override; + void accept(Visitor* v) override; + dinteger_t getInteger(); + IntegerExp* syntaxCopy() override; + static IntegerExp* createBool(bool b); +}; + +class IntervalExp final : public Expression +{ +public: + Expression* lwr; + Expression* upr; + Expression* syntaxCopy() override; + void accept(Visitor* v) override; +}; + +class IsExp final : public Expression +{ +public: + Type* targ; + Identifier* id; + Type* tspec; + Array* parameters; + TOK tok; + TOK tok2; + IsExp* syntaxCopy() override; + void accept(Visitor* v) override; +}; + +enum : bool { LOGSEMANTIC = false }; + +class LineInitExp final : public DefaultInitExp +{ +public: + void accept(Visitor* v) override; +}; + +class LogicalExp final : public BinExp +{ +public: + void accept(Visitor* v) override; +}; + +class LoweredAssignExp final : public AssignExp +{ +public: + Expression* lowering; + const char* toChars() const override; + void accept(Visitor* v) override; +}; + +class MinAssignExp final : public BinAssignExp +{ +public: + void accept(Visitor* v) override; +}; + +class MinExp final : public BinExp +{ +public: + void accept(Visitor* v) override; +}; + +class MixinExp final : public Expression +{ +public: + Array* exps; + MixinExp* syntaxCopy() override; + bool equals(const RootObject* const o) const override; + void accept(Visitor* v) override; +}; + +class ModAssignExp final : public BinAssignExp +{ +public: + void accept(Visitor* v) override; +}; + +class ModExp final : public BinExp +{ +public: + void accept(Visitor* v) override; +}; + +enum class Modifiable +{ + no = 0, + yes = 1, + initialization = 2, +}; + +enum class ModifyFlags +{ + none = 0, + noError = 1, + fieldAssign = 2, +}; + +class ModuleInitExp final : public DefaultInitExp +{ +public: + void accept(Visitor* v) override; +}; + +class MulAssignExp final : public BinAssignExp +{ +public: + void accept(Visitor* v) override; +}; + +class MulExp final : public BinExp +{ +public: + void accept(Visitor* v) override; +}; + +class NegExp final : public UnaExp +{ +public: + void accept(Visitor* v) override; +}; + +class NewAnonClassExp final : public Expression +{ +public: + Expression* thisexp; + ClassDeclaration* cd; + Array* arguments; + NewAnonClassExp* syntaxCopy() override; + void accept(Visitor* v) override; +}; + +class NewExp final : public Expression +{ +public: + Expression* thisexp; + Type* newtype; + Array* arguments; + Array* names; + Expression* argprefix; + CtorDeclaration* member; + bool onstack; + bool thrownew; + Expression* lowering; + static NewExp* create(const Loc& loc, Expression* thisexp, Type* newtype, Array* arguments); + NewExp* syntaxCopy() override; + void accept(Visitor* v) override; +}; + +class NotExp final : public UnaExp +{ +public: + void accept(Visitor* v) override; +}; + +class NullExp final : public Expression +{ +public: + bool equals(const RootObject* const o) const override; + Optional toBool() override; + StringExp* toStringExp() override; + void accept(Visitor* v) override; +}; + +class ObjcClassReferenceExp final : public Expression +{ +public: + ClassDeclaration* classDeclaration; + void accept(Visitor* v) override; +}; + +class OrAssignExp final : public BinAssignExp +{ +public: + void accept(Visitor* v) override; +}; + +class OrExp final : public BinExp +{ +public: + void accept(Visitor* v) override; +}; + +class OverExp final : public Expression +{ +public: + OverloadSet* vars; + bool isLvalue() override; + void accept(Visitor* v) override; +}; + +class PostExp final : public BinExp +{ +public: + void accept(Visitor* v) override; +}; + +class PowAssignExp final : public BinAssignExp +{ +public: + void accept(Visitor* v) override; +}; + +class PowExp final : public BinExp +{ +public: + void accept(Visitor* v) override; +}; + +class PreExp final : public UnaExp +{ +public: + void accept(Visitor* v) override; +}; + +class PrettyFuncInitExp final : public DefaultInitExp +{ +public: + void accept(Visitor* v) override; +}; + +class PtrExp final : public UnaExp +{ +public: + bool isLvalue() override; + void accept(Visitor* v) override; +}; + +class RealExp final : public Expression +{ +public: + _d_real value; + static RealExp* create(const Loc& loc, _d_real value, Type* type); + bool equals(const RootObject* const o) const override; + bool isIdentical(const Expression* const e) const override; + dinteger_t toInteger() override; + uinteger_t toUInteger() override; + _d_real toReal() override; + _d_real toImaginary() override; + complex_t toComplex() override; + Optional toBool() override; + void accept(Visitor* v) override; +}; + +class RemoveExp final : public BinExp +{ +public: + void accept(Visitor* v) override; +}; + +class ScopeExp final : public Expression +{ +public: + ScopeDsymbol* sds; + ScopeExp* syntaxCopy() override; + bool checkType() override; + bool checkValue() override; + void accept(Visitor* v) override; +}; + +class ShlAssignExp final : public BinAssignExp +{ +public: + void accept(Visitor* v) override; +}; + +class ShlExp final : public BinExp +{ +public: + void accept(Visitor* v) override; +}; + +class ShrAssignExp final : public BinAssignExp +{ +public: + void accept(Visitor* v) override; +}; + +class ShrExp final : public BinExp +{ +public: + void accept(Visitor* v) override; +}; + +class SliceExp final : public UnaExp +{ +public: + Expression* upr; + Expression* lwr; + VarDeclaration* lengthVar; +private: + struct BitFields final + { + bool upperIsInBounds; + bool lowerIsLessThanUpper; + bool arrayop; + BitFields() : + upperIsInBounds(), + lowerIsLessThanUpper(), + arrayop() + { + } + BitFields(bool upperIsInBounds, bool lowerIsLessThanUpper = false, bool arrayop = false) : + upperIsInBounds(upperIsInBounds), + lowerIsLessThanUpper(lowerIsLessThanUpper), + arrayop(arrayop) + {} + }; + +public: + bool upperIsInBounds() const; + bool upperIsInBounds(bool v); + bool lowerIsLessThanUpper() const; + bool lowerIsLessThanUpper(bool v); + bool arrayop() const; + bool arrayop(bool v); +private: + uint8_t bitFields; +public: + SliceExp* syntaxCopy() override; + bool isLvalue() override; + Optional toBool() override; + void accept(Visitor* v) override; +}; + +class StringExp final : public Expression +{ +public: + char postfix; + OwnedBy ownedByCtfe; + union + { + char* string; + char16_t* wstring; + char32_t* dstring; + }; + size_t len; + uint8_t sz; + bool committed; + bool hexString; + enum : char { NoPostfix = 0u }; + + static StringExp* create(const Loc& loc, const char* s); + static StringExp* create(const Loc& loc, const void* string, size_t len); + bool equals(const RootObject* const o) const override; + size_t numberOfCodeUnits(int32_t tynto = 0) const; + void writeTo(void* dest, bool zero, int32_t tyto = 0) const; + char32_t getCodeUnit(size_t i) const; + StringExp* toStringExp() override; + int32_t compare(const StringExp* const se2) const; + Optional toBool() override; + bool isLvalue() override; + void accept(Visitor* v) override; +}; + +class StructLiteralExp final : public Expression +{ +public: + StructDeclaration* sd; + Array* elements; + Type* stype; + union + { + Symbol* sym; + StructLiteralExp* inlinecopy; + }; + StructLiteralExp* origin; + uint8_t stageflags; + bool useStaticInit; + bool isOriginal; + OwnedBy ownedByCtfe; + static StructLiteralExp* create(const Loc& loc, StructDeclaration* sd, void* elements, Type* stype = nullptr); + bool equals(const RootObject* const o) const override; + StructLiteralExp* syntaxCopy() override; + void accept(Visitor* v) override; +}; + +class ThisExp : public Expression +{ +public: + VarDeclaration* var; + ThisExp(const Loc& loc, const EXP tok); + ThisExp* syntaxCopy() override; + Optional toBool() override; + bool isLvalue() final override; + void accept(Visitor* v) override; +}; + +class SuperExp final : public ThisExp +{ +public: + void accept(Visitor* v) override; +}; + +class SymbolExp : public Expression +{ +public: + Declaration* var; + Dsymbol* originalScope; + bool hasOverloads; + void accept(Visitor* v) override; +}; + +class SymOffExp final : public SymbolExp +{ +public: + dinteger_t offset; + Optional toBool() override; + void accept(Visitor* v) override; +}; + +class TemplateExp final : public Expression +{ +public: + TemplateDeclaration* td; + FuncDeclaration* fd; + bool isLvalue() override; + bool checkType() override; + bool checkValue() override; + void accept(Visitor* v) override; +}; + +class ThrowExp final : public UnaExp +{ +public: + ThrowExp* syntaxCopy() override; + void accept(Visitor* v) override; +}; + +class ThrownExceptionExp final : public Expression +{ +public: + ClassReferenceExp* thrown; + const char* toChars() const override; + void accept(Visitor* v) override; +}; + +class TraitsExp final : public Expression +{ +public: + Identifier* ident; + Array* args; + TraitsExp* syntaxCopy() override; + void accept(Visitor* v) override; +}; + +class TupleExp final : public Expression +{ +public: + Expression* e0; + Array* exps; + static TupleExp* create(const Loc& loc, Array* exps); + TupleExp* syntaxCopy() override; + bool equals(const RootObject* const o) const override; + void accept(Visitor* v) override; +}; + +class TypeExp final : public Expression +{ +public: + bool parens; + TypeExp* syntaxCopy() override; + bool checkType() override; + bool checkValue() override; + void accept(Visitor* v) override; +}; + +class TypeidExp final : public Expression +{ +public: + RootObject* obj; + TypeidExp* syntaxCopy() override; + void accept(Visitor* v) override; +}; + +class UAddExp final : public UnaExp +{ +public: + void accept(Visitor* v) override; +}; + +class UshrAssignExp final : public BinAssignExp +{ +public: + void accept(Visitor* v) override; +}; + +class UshrExp final : public BinExp +{ +public: + void accept(Visitor* v) override; +}; + +class VarExp final : public SymbolExp +{ +public: + bool delegateWasExtracted; + static VarExp* create(const Loc& loc, Declaration* var, bool hasOverloads = true); + bool equals(const RootObject* const o) const override; + bool isLvalue() override; + void accept(Visitor* v) override; +}; + +class VectorArrayExp final : public UnaExp +{ +public: + bool isLvalue() override; + void accept(Visitor* v) override; +}; + +class VectorExp final : public UnaExp +{ +public: + TypeVector* to; + uint32_t dim; + OwnedBy ownedByCtfe; + static VectorExp* create(const Loc& loc, Expression* e, Type* t); + VectorExp* syntaxCopy() override; + void accept(Visitor* v) override; +}; + +class VoidInitExp final : public Expression +{ +public: + VarDeclaration* var; + void accept(Visitor* v) override; +}; + +enum : int32_t { WANTexpand = 1 }; + +enum : int32_t { WANTvalue = 0 }; + +class XorAssignExp final : public BinAssignExp +{ +public: + void accept(Visitor* v) override; +}; + +class XorExp final : public BinExp +{ +public: + void accept(Visitor* v) override; +}; + +extern void expandTuples(Array* exps, Array* names = nullptr); + +enum : int32_t { stageApply = 8 }; + +enum : int32_t { stageInlineScan = 16 }; + +enum : int32_t { stageOptimize = 4 }; + +enum : int32_t { stageScrub = 1 }; + +enum : int32_t { stageSearchPointers = 2 }; + +enum : int32_t { stageToCBuffer = 32 }; + +struct AttributeViolation final +{ + Loc loc; + const char* fmtStr; + RootObject* arg0; + RootObject* arg1; + RootObject* arg2; + AttributeViolation() : + loc(Loc(0u, 0u, 0u)), + fmtStr(nullptr), + arg0(nullptr), + arg1(nullptr), + arg2(nullptr) + { + } + AttributeViolation(Loc loc, const char* fmtStr = nullptr, RootObject* arg0 = nullptr, RootObject* arg1 = nullptr, RootObject* arg2 = nullptr) : + loc(loc), + fmtStr(fmtStr), + arg0(arg0), + arg1(arg1), + arg2(arg2) + {} +}; + +enum class ILS : uint8_t +{ + uninitialized = 0u, + no = 1u, + yes = 2u, +}; + +enum class PINLINE : uint8_t +{ + default_ = 0u, + never = 1u, + always = 2u, +}; + +struct ObjcFuncDeclaration final +{ + ObjcSelector* selector; + VarDeclaration* selectorParameter; + bool isOptional; + ObjcFuncDeclaration() : + selector(), + selectorParameter(), + isOptional() + { + } + ObjcFuncDeclaration(ObjcSelector* selector, VarDeclaration* selectorParameter = nullptr, bool isOptional = false) : + selector(selector), + selectorParameter(selectorParameter), + isOptional(isOptional) + {} +}; + +enum class PURE : uint8_t +{ + impure = 0u, + fwdref = 1u, + weak = 2u, + const_ = 3u, +}; + +enum class VarArg : uint8_t +{ + none = 0u, + variadic = 1u, + typesafe = 2u, + KRvariadic = 3u, +}; + +struct ParameterList final +{ + Array* parameters; + StorageClass stc; + VarArg varargs; + bool hasIdentifierList; + ParameterList(Array* parameters, VarArg varargs = (VarArg)0u, StorageClass stc = 0); + size_t length(); + Parameter* opIndex(size_t i); + ParameterList() : + parameters(), + stc(), + varargs((VarArg)0u), + hasIdentifierList() { } }; -class Visitor : public ParseTimeVisitor +class FuncDeclaration : public Declaration +{ +public: + Statement* fbody; + Array foverrides; +private: + ContractInfo* contracts; +public: + const char* mangleString; + VarDeclaration* vresult; + LabelDsymbol* returnLabel; + void* isTypeIsolatedCache; + DsymbolTable* localsymtab; + VarDeclaration* vthis; + VarDeclaration* v_arguments; + VarDeclaration* v_argptr; + Array* parameters; + DsymbolTable* labtab; + Dsymbol* overnext; + FuncDeclaration* overnext0; + Loc endloc; + int32_t vtblIndex; + ILS inlineStatusStmt; + ILS inlineStatusExp; + PINLINE inlining; + int32_t inlineNest; + ForeachStatement* fes; + BaseClass* interfaceVirtual; + Type* tintro; + StorageClass storage_class2; + int32_t hasReturnExp; + VarDeclaration* nrvo_var; + Symbol* shidden; + Array* returns; + Array* gotos; + Array* alignSectionVars; + Symbol* salignSection; + BUILTIN builtin; + int32_t tookAddressOf; + bool requiresClosure; + Array closureVars; + Array outerVars; + Array siblingCallers; + Array* inlinedNestedCallees; + AttributeViolation* safetyViolation; + AttributeViolation* nogcViolation; + AttributeViolation* pureViolation; + AttributeViolation* nothrowViolation; + bool purityInprocess() const; + bool purityInprocess(bool v); + bool safetyInprocess() const; + bool safetyInprocess(bool v); + bool nothrowInprocess() const; + bool nothrowInprocess(bool v); + bool nogcInprocess() const; + bool nogcInprocess(bool v); + bool returnInprocess() const; + bool returnInprocess(bool v); + bool inlineScanned() const; + bool inlineScanned(bool v); + bool inferScope() const; + bool inferScope(bool v); + bool hasCatches() const; + bool hasCatches(bool v); + bool skipCodegen() const; + bool skipCodegen(bool v); + bool printf() const; + bool printf(bool v); + bool scanf() const; + bool scanf(bool v); + bool noreturn() const; + bool noreturn(bool v); + bool isNRVO() const; + bool isNRVO(bool v); + bool isNaked() const; + bool isNaked(bool v); + bool isGenerated() const; + bool isGenerated(bool v); + bool isIntroducing() const; + bool isIntroducing(bool v); + bool hasSemantic3Errors() const; + bool hasSemantic3Errors(bool v); + bool hasNoEH() const; + bool hasNoEH(bool v); + bool inferRetType() const; + bool inferRetType(bool v); + bool hasDualContext() const; + bool hasDualContext(bool v); + bool hasAlwaysInlines() const; + bool hasAlwaysInlines(bool v); + bool isCrtCtor() const; + bool isCrtCtor(bool v); + bool isCrtDtor() const; + bool isCrtDtor(bool v); + bool hasEscapingSiblings() const; + bool hasEscapingSiblings(bool v); + bool computedEscapingSiblings() const; + bool computedEscapingSiblings(bool v); + bool dllImport() const; + bool dllImport(bool v); + bool dllExport() const; + bool dllExport(bool v); +private: + uint32_t bitFields; +public: + ObjcFuncDeclaration objc; + static FuncDeclaration* create(const Loc& loc, const Loc& endloc, Identifier* id, StorageClass storage_class, Type* type, bool noreturn = false); + Array* frequires(); + Array* fensures(); + Statement* frequire(); + Statement* fensure(); + FuncDeclaration* fdrequire(); + FuncDeclaration* fdensure(); + Array* fdrequireParams(); + Array* fdensureParams(); + Array* frequires(Array* param); + Array* fensures(Array* param); + Statement* frequire(Statement* param); + Statement* fensure(Statement* param); + FuncDeclaration* fdrequire(FuncDeclaration* param); + FuncDeclaration* fdensure(FuncDeclaration* param); + Array* fdrequireParams(Array* param); + Array* fdensureParams(Array* param); + FuncDeclaration* syntaxCopy(Dsymbol* s) override; + bool functionSemantic(); + bool functionSemantic3(); + bool equals(const RootObject* const o) const final override; + int32_t findVtblIndex(Array* vtbl, int32_t dim); + bool overloadInsert(Dsymbol* s) override; + bool inUnittest(); + MATCH leastAsSpecialized(FuncDeclaration* g, Array* names); + LabelDsymbol* searchLabel(Identifier* ident, const Loc& loc = Loc::initial); + enum : int32_t { LevelError = -2 }; + + const char* toPrettyChars(bool QualifyTypes = false) override; + const char* toFullSignature(); + bool isMain() const; + bool isCMain() const; + bool isWinMain() const; + bool isDllMain() const; + bool isRtInit() const; + bool isExport() const final override; + bool isImportedSymbol() const final override; + bool isCodeseg() const final override; + bool isOverloadable() const final override; + bool isAbstract() final override; + bool canInferAttributes(Scope* sc); + void initInferAttributes(); + PURE isPure(); + bool isSafe(); + bool isTrusted(); + bool isNogc(); + virtual bool isNested() const; + AggregateDeclaration* isThis() override; + bool needThis() final override; + bool isVirtualMethod(); + virtual bool isVirtual() const; + bool isFinalFunc() const; + virtual bool addPreInvariant(); + virtual bool addPostInvariant(); + const char* kind() const override; + bool isUnique() const; + bool needsClosure(); + bool checkClosure(); + bool hasNestedFrameRefs(); + static bool needsFensure(FuncDeclaration* fd); + void buildEnsureRequire(); + ParameterList getParameterList(); + static FuncDeclaration* genCfunc(Array* fparams, Type* treturn, const char* name, StorageClass stc = 0); + static FuncDeclaration* genCfunc(Array* fparams, Type* treturn, Identifier* id, StorageClass stc = 0); + FuncDeclaration* isFuncDeclaration() final override; + virtual FuncDeclaration* toAliasFunc(); + void accept(Visitor* v) override; +}; + +class CtorDeclaration final : public FuncDeclaration { public: - using ParseTimeVisitor::visit; - virtual void visit(ErrorStatement* s); - virtual void visit(PeelStatement* s); - virtual void visit(UnrolledLoopStatement* s); - virtual void visit(SwitchErrorStatement* s); - virtual void visit(DebugStatement* s); - virtual void visit(DtorExpStatement* s); - virtual void visit(ForwardingStatement* s); - virtual void visit(OverloadSet* s); - virtual void visit(LabelDsymbol* s); - virtual void visit(WithScopeSymbol* s); - virtual void visit(ArrayScopeSymbol* s); - virtual void visit(OverDeclaration* s); - virtual void visit(SymbolDeclaration* s); - virtual void visit(ForwardingAttribDeclaration* s); - virtual void visit(ThisDeclaration* s); - virtual void visit(TypeInfoDeclaration* s); - virtual void visit(TypeInfoStructDeclaration* s); - virtual void visit(TypeInfoClassDeclaration* s); - virtual void visit(TypeInfoInterfaceDeclaration* s); - virtual void visit(TypeInfoPointerDeclaration* s); - virtual void visit(TypeInfoArrayDeclaration* s); - virtual void visit(TypeInfoStaticArrayDeclaration* s); - virtual void visit(TypeInfoAssociativeArrayDeclaration* s); - virtual void visit(TypeInfoEnumDeclaration* s); - virtual void visit(TypeInfoFunctionDeclaration* s); - virtual void visit(TypeInfoDelegateDeclaration* s); - virtual void visit(TypeInfoTupleDeclaration* s); - virtual void visit(TypeInfoConstDeclaration* s); - virtual void visit(TypeInfoInvariantDeclaration* s); - virtual void visit(TypeInfoSharedDeclaration* s); - virtual void visit(TypeInfoWildDeclaration* s); - virtual void visit(TypeInfoVectorDeclaration* s); - virtual void visit(FuncAliasDeclaration* s); - virtual void visit(ErrorInitializer* i); - virtual void visit(ErrorExp* e); - virtual void visit(ComplexExp* e); - virtual void visit(StructLiteralExp* e); - virtual void visit(CompoundLiteralExp* e); - virtual void visit(ObjcClassReferenceExp* e); - virtual void visit(SymOffExp* e); - virtual void visit(OverExp* e); - virtual void visit(HaltExp* e); - virtual void visit(DotTemplateExp* e); - virtual void visit(DotVarExp* e); - virtual void visit(DelegateExp* e); - virtual void visit(DotTypeExp* e); - virtual void visit(VectorExp* e); - virtual void visit(VectorArrayExp* e); - virtual void visit(SliceExp* e); - virtual void visit(ArrayLengthExp* e); - virtual void visit(DelegatePtrExp* e); - virtual void visit(DelegateFuncptrExp* e); - virtual void visit(DotExp* e); - virtual void visit(IndexExp* e); - virtual void visit(ConstructExp* e); - virtual void visit(BlitExp* e); - virtual void visit(RemoveExp* e); - virtual void visit(ClassReferenceExp* e); - virtual void visit(VoidInitExp* e); - virtual void visit(ThrownExceptionExp* e); - virtual void visit(LoweredAssignExp* e); + bool isCpCtor; + CtorDeclaration* syntaxCopy(Dsymbol* s) override; + const char* kind() const override; + const char* toChars() const override; + bool isVirtual() const override; + bool addPreInvariant() override; + bool addPostInvariant() override; + CtorDeclaration* isCtorDeclaration() override; + void accept(Visitor* v) override; }; -class StoppableVisitor : public Visitor +class DtorDeclaration final : public FuncDeclaration { public: - using Visitor::visit; - bool stop; + DtorDeclaration* syntaxCopy(Dsymbol* s) override; + const char* kind() const override; + const char* toChars() const override; + bool isVirtual() const override; + bool addPreInvariant() override; + bool addPostInvariant() override; + bool overloadInsert(Dsymbol* s) override; + DtorDeclaration* isDtorDeclaration() override; + void accept(Visitor* v) override; }; -struct TargetC final +class FuncAliasDeclaration final : public FuncDeclaration { - enum class Runtime : uint8_t - { - Unspecified = 0u, - Bionic = 1u, - DigitalMars = 2u, - Glibc = 3u, - Microsoft = 4u, - Musl = 5u, - Newlib = 6u, - UClibc = 7u, - WASI = 8u, - }; +public: + FuncDeclaration* funcalias; + bool hasOverloads; + FuncAliasDeclaration* isFuncAliasDeclaration() override; + const char* kind() const override; + FuncDeclaration* toAliasFunc() override; + void accept(Visitor* v) override; +}; - enum class BitFieldStyle : uint8_t - { - Unspecified = 0u, - DM = 1u, - MS = 2u, - Gcc_Clang = 3u, - }; +class FuncLiteralDeclaration final : public FuncDeclaration +{ +public: + TOK tok; + Type* treq; + bool deferToObj; + FuncLiteralDeclaration* syntaxCopy(Dsymbol* s) override; + bool isNested() const override; + AggregateDeclaration* isThis() override; + bool isVirtual() const override; + bool addPreInvariant() override; + bool addPostInvariant() override; + FuncLiteralDeclaration* isFuncLiteralDeclaration() override; + const char* kind() const override; + const char* toPrettyChars(bool QualifyTypes = false) override; + void accept(Visitor* v) override; +}; - bool crtDestructorsSupported; - uint8_t boolsize; - uint8_t shortsize; - uint8_t intsize; - uint8_t longsize; - uint8_t long_longsize; - uint8_t long_doublesize; - uint8_t wchar_tsize; - Runtime runtime; - BitFieldStyle bitFieldStyle; - TargetC() : - crtDestructorsSupported(true), - boolsize(), - shortsize(), - intsize(), - longsize(), - long_longsize(), - long_doublesize(), - wchar_tsize() - { - } - TargetC(bool crtDestructorsSupported, uint8_t boolsize = 0u, uint8_t shortsize = 0u, uint8_t intsize = 0u, uint8_t longsize = 0u, uint8_t long_longsize = 0u, uint8_t long_doublesize = 0u, uint8_t wchar_tsize = 0u, Runtime runtime = (Runtime)0u, BitFieldStyle bitFieldStyle = (BitFieldStyle)0u) : - crtDestructorsSupported(crtDestructorsSupported), - boolsize(boolsize), - shortsize(shortsize), - intsize(intsize), - longsize(longsize), - long_longsize(long_longsize), - long_doublesize(long_doublesize), - wchar_tsize(wchar_tsize), - runtime(runtime), - bitFieldStyle(bitFieldStyle) - {} +enum class FuncResolveFlag : uint8_t +{ + standard = 0u, + quiet = 1u, + overloadOnly = 2u, + ufcs = 4u, +}; + +class InvariantDeclaration final : public FuncDeclaration +{ +public: + InvariantDeclaration* syntaxCopy(Dsymbol* s) override; + bool isVirtual() const override; + bool addPreInvariant() override; + bool addPostInvariant() override; + InvariantDeclaration* isInvariantDeclaration() override; + void accept(Visitor* v) override; +}; + +class NewDeclaration final : public FuncDeclaration +{ +public: + NewDeclaration* syntaxCopy(Dsymbol* s) override; + const char* kind() const override; + bool isVirtual() const override; + bool addPreInvariant() override; + bool addPostInvariant() override; + NewDeclaration* isNewDeclaration() override; + void accept(Visitor* v) override; }; -struct TargetCPP final +class SemanticTimePermissiveVisitor : public Visitor { - enum class Runtime : uint8_t - { - Unspecified = 0u, - Clang = 1u, - DigitalMars = 2u, - Gcc = 3u, - Microsoft = 4u, - Sun = 5u, - }; +public: + using Visitor::visit; + void visit(Dsymbol* __param_0_) override; + void visit(Parameter* __param_0_) override; + void visit(Statement* __param_0_) override; + void visit(Type* __param_0_) override; + void visit(Expression* __param_0_) override; + void visit(TemplateParameter* __param_0_) override; + void visit(Condition* __param_0_) override; + void visit(Initializer* __param_0_) override; +}; - bool reverseOverloads; - bool exceptions; - bool twoDtorInVtable; - bool splitVBasetable; - bool wrapDtorInExternD; - Runtime runtime; - const char* toMangle(Dsymbol* s); - const char* typeInfoMangle(ClassDeclaration* cd); - const char* thunkMangle(FuncDeclaration* fd, int32_t offset); - const char* typeMangle(Type* t); - Type* parameterType(Type* t); - bool fundamentalType(const Type* const t, bool& isFundamental); - uint32_t derivedClassOffset(ClassDeclaration* baseClass); - TargetCPP() : - reverseOverloads(), - exceptions(), - twoDtorInVtable(), - splitVBasetable(), - wrapDtorInExternD() - { - } - TargetCPP(bool reverseOverloads, bool exceptions = false, bool twoDtorInVtable = false, bool splitVBasetable = false, bool wrapDtorInExternD = false, Runtime runtime = (Runtime)0u) : - reverseOverloads(reverseOverloads), - exceptions(exceptions), - twoDtorInVtable(twoDtorInVtable), - splitVBasetable(splitVBasetable), - wrapDtorInExternD(wrapDtorInExternD), - runtime(runtime) - {} +class StatementRewriteWalker : public SemanticTimePermissiveVisitor +{ +public: + using SemanticTimePermissiveVisitor::visit; + Statement** ps; + void visitStmt(Statement*& s); + void replaceCurrent(Statement* s); + void visit(PeelStatement* s) override; + void visit(CompoundStatement* s) override; + void visit(CompoundDeclarationStatement* s) override; + void visit(UnrolledLoopStatement* s) override; + void visit(ScopeStatement* s) override; + void visit(WhileStatement* s) override; + void visit(DoStatement* s) override; + void visit(ForStatement* s) override; + void visit(ForeachStatement* s) override; + void visit(ForeachRangeStatement* s) override; + void visit(IfStatement* s) override; + void visit(SwitchStatement* s) override; + void visit(CaseStatement* s) override; + void visit(CaseRangeStatement* s) override; + void visit(DefaultStatement* s) override; + void visit(SynchronizedStatement* s) override; + void visit(WithStatement* s) override; + void visit(TryCatchStatement* s) override; + void visit(TryFinallyStatement* s) override; + void visit(DebugStatement* s) override; + void visit(LabelStatement* s) override; }; -struct TargetObjC final +class NrvoWalker final : public StatementRewriteWalker { - bool supported; - TargetObjC() : - supported() - { - } - TargetObjC(bool supported) : - supported(supported) - {} +public: + using StatementRewriteWalker::visit; + FuncDeclaration* fd; + Scope* sc; + void visit(ReturnStatement* s) override; + void visit(TryFinallyStatement* s) override; }; -enum class CPU : uint8_t +class PostBlitDeclaration final : public FuncDeclaration { - x87 = 0u, - mmx = 1u, - sse = 2u, - sse2 = 3u, - sse3 = 4u, - ssse3 = 5u, - sse4_1 = 6u, - sse4_2 = 7u, - avx = 8u, - avx2 = 9u, - avx512 = 10u, - baseline = 11u, - native = 12u, +public: + PostBlitDeclaration* syntaxCopy(Dsymbol* s) override; + bool isVirtual() const override; + bool addPreInvariant() override; + bool addPostInvariant() override; + bool overloadInsert(Dsymbol* s) override; + PostBlitDeclaration* isPostBlitDeclaration() override; + void accept(Visitor* v) override; }; -enum class ErrorKind +class StaticCtorDeclaration : public FuncDeclaration { - warning = 0, - deprecation = 1, - error = 2, - tip = 3, - message = 4, +public: + StaticCtorDeclaration* syntaxCopy(Dsymbol* s) override; + AggregateDeclaration* isThis() final override; + bool isVirtual() const final override; + bool addPreInvariant() final override; + bool addPostInvariant() final override; + bool hasStaticCtorOrDtor() final override; + StaticCtorDeclaration* isStaticCtorDeclaration() final override; + void accept(Visitor* v) override; }; -typedef _d_real longdouble; +class SharedStaticCtorDeclaration final : public StaticCtorDeclaration +{ +public: + SharedStaticCtorDeclaration* syntaxCopy(Dsymbol* s) override; + SharedStaticCtorDeclaration* isSharedStaticCtorDeclaration() override; + void accept(Visitor* v) override; +}; -typedef uint64_t uint64_t; +class StaticDtorDeclaration : public FuncDeclaration +{ +public: + VarDeclaration* vgate; + StaticDtorDeclaration* syntaxCopy(Dsymbol* s) override; + AggregateDeclaration* isThis() final override; + bool isVirtual() const final override; + bool hasStaticCtorOrDtor() final override; + bool addPreInvariant() final override; + bool addPostInvariant() final override; + StaticDtorDeclaration* isStaticDtorDeclaration() final override; + void accept(Visitor* v) override; +}; -class AggregateDeclaration : public ScopeDsymbol +class SharedStaticDtorDeclaration final : public StaticDtorDeclaration { public: - Type* type; - StorageClass storage_class; - uint32_t structsize; - uint32_t alignsize; - Array fields; - Dsymbol* deferred; - ClassKind classKind; - CPPMANGLE cppmangle; - MangleOverride* pMangleOverride; - Dsymbol* enclosing; - VarDeclaration* vthis; - VarDeclaration* vthis2; - Array invs; - FuncDeclaration* inv; - Dsymbol* ctor; - CtorDeclaration* defaultCtor; - AliasThis* aliasthis; - Array userDtors; - DtorDeclaration* aggrDtor; - DtorDeclaration* dtor; - DtorDeclaration* tidtor; - DtorDeclaration* fieldDtor; - Expression* getRTInfo; - Visibility visibility; - bool noDefaultCtor; - bool disableNew; - Sizeok sizeok; - virtual Scope* newScope(Scope* sc); - virtual void finalizeSize() = 0; - uinteger_t size(const Loc& loc) final override; - bool fill(const Loc& loc, Array& elements, bool ctorinit); - Type* getType() final override; - bool isDeprecated() const final override; - bool isNested() const; - bool isExport() const final override; - Visibility visible() final override; - Type* handleType(); - bool hasInvariant(); - void* sinit; - AggregateDeclaration* isAggregateDeclaration() final override; + SharedStaticDtorDeclaration* syntaxCopy(Dsymbol* s) override; + SharedStaticDtorDeclaration* isSharedStaticDtorDeclaration() override; + void accept(Visitor* v) override; +}; + +class UnitTestDeclaration final : public FuncDeclaration +{ +public: + char* codedoc; + Array deferredNested; + UnitTestDeclaration* syntaxCopy(Dsymbol* s) override; + AggregateDeclaration* isThis() override; + bool isVirtual() const override; + bool addPreInvariant() override; + bool addPostInvariant() override; + UnitTestDeclaration* isUnitTestDeclaration() override; void accept(Visitor* v) override; }; -class AliasThis final : public Dsymbol -{ -public: - Identifier* ident; - Dsymbol* sym; - bool isDeprecated_; - AliasThis* syntaxCopy(Dsymbol* s) override; - const char* kind() const override; - AliasThis* isAliasThis(); - void accept(Visitor* v) override; - bool isDeprecated() const override; -}; +struct HdrGenState final +{ + bool hdrgen; + bool ddoc; + bool fullDump; + bool importcHdr; + bool fullQual; + int32_t tpltMember; + int32_t autoMember; + int32_t forStmtInit; + int32_t insideFuncBody; + int32_t insideAggregate; + bool declstring; + EnumDeclaration* inEnumDecl; + HdrGenState() : + hdrgen(), + ddoc(), + fullDump(), + importcHdr(), + fullQual(), + tpltMember(), + autoMember(), + forStmtInit(), + insideFuncBody(), + insideAggregate(), + declstring(), + inEnumDecl() + { + } + HdrGenState(bool hdrgen, bool ddoc = false, bool fullDump = false, bool importcHdr = false, bool fullQual = false, int32_t tpltMember = 0, int32_t autoMember = 0, int32_t forStmtInit = 0, int32_t insideFuncBody = 0, int32_t insideAggregate = 0, bool declstring = false, EnumDeclaration* inEnumDecl = nullptr) : + hdrgen(hdrgen), + ddoc(ddoc), + fullDump(fullDump), + importcHdr(importcHdr), + fullQual(fullQual), + tpltMember(tpltMember), + autoMember(autoMember), + forStmtInit(forStmtInit), + insideFuncBody(insideFuncBody), + insideAggregate(insideAggregate), + declstring(declstring), + inEnumDecl(inEnumDecl) + {} +}; + +enum : int32_t { TEST_EMIT_ALL = 0 }; -extern TypeTuple* toArgTypes_x86(Type* t); +extern void genhdrfile(Module* m, OutBuffer& buf); -extern TypeTuple* toArgTypes_sysv_x64(Type* t); +extern void moduleToBuffer(OutBuffer& buf, Module* m); -extern TypeTuple* toArgTypes_aarch64(Type* t); +extern const char* parametersTypeToChars(ParameterList pl); -extern bool isHFVA(Type* t, int32_t maxNumElements = 4, Type** rewriteType = nullptr); +extern const char* toChars(const Statement* const s); -struct structalign_t final +enum class InitKind : uint8_t { -private: - uint16_t value; - bool pack; -public: - bool isDefault() const; - void setDefault(); - bool isUnknown() const; - void setUnknown(); - void set(uint32_t value); - uint32_t get() const; - bool isPack() const; - void setPack(bool pack); - structalign_t() : - value(0u), - pack() - { - } - structalign_t(uint16_t value, bool pack = false) : - value(value), - pack(pack) - {} + void_ = 0u, + default_ = 1u, + error = 2u, + struct_ = 3u, + array = 4u, + exp = 5u, + C_ = 6u, }; -class AttribDeclaration : public Dsymbol +class Initializer : public ASTNode { public: - Array* decl; - virtual Array* include(Scope* sc); - virtual Scope* newScope(Scope* sc); - void importAll(Scope* sc) override; - void addComment(const char* comment) override; - const char* kind() const override; - bool oneMember(Dsymbol** ps, Identifier* ident) override; - void setFieldOffset(AggregateDeclaration* ad, FieldState& fieldState, bool isunion) override; - bool hasPointers() final override; - bool hasStaticCtorOrDtor() final override; - void checkCtorConstInit() final override; - void addObjcSymbols(Array* classes, Array* categories) final override; - AttribDeclaration* isAttribDeclaration() override; + Loc loc; + InitKind kind; + DYNCAST dyncast() const override; + ErrorInitializer* isErrorInitializer(); + VoidInitializer* isVoidInitializer(); + DefaultInitializer* isDefaultInitializer(); + StructInitializer* isStructInitializer(); + ArrayInitializer* isArrayInitializer(); + ExpInitializer* isExpInitializer(); + CInitializer* isCInitializer(); void accept(Visitor* v) override; }; -class StorageClassDeclaration : public AttribDeclaration +class ArrayInitializer final : public Initializer { public: - StorageClass stc; - StorageClassDeclaration* syntaxCopy(Dsymbol* s) override; - Scope* newScope(Scope* sc) override; - bool oneMember(Dsymbol** ps, Identifier* ident) final override; - StorageClassDeclaration* isStorageClassDeclaration() override; + Array index; + Array value; + uint32_t dim; + Type* type; + bool sem; + bool isCarray; + bool isAssociativeArray() const; void accept(Visitor* v) override; }; -class DeprecatedDeclaration final : public StorageClassDeclaration +class CInitializer final : public Initializer { public: - Expression* msg; - const char* msgstr; - DeprecatedDeclaration* syntaxCopy(Dsymbol* s) override; - Scope* newScope(Scope* sc) override; + Array initializerList; + Type* type; + bool sem; void accept(Visitor* v) override; }; -class LinkDeclaration final : public AttribDeclaration +class DefaultInitializer final : public Initializer { public: - LINK linkage; - static LinkDeclaration* create(const Loc& loc, LINK p, Array* decl); - LinkDeclaration* syntaxCopy(Dsymbol* s) override; - Scope* newScope(Scope* sc) override; - const char* toChars() const override; + Type* type; void accept(Visitor* v) override; }; -class CPPMangleDeclaration final : public AttribDeclaration +class ErrorInitializer final : public Initializer { public: - CPPMANGLE cppmangle; - CPPMangleDeclaration* syntaxCopy(Dsymbol* s) override; - Scope* newScope(Scope* sc) override; - const char* toChars() const override; void accept(Visitor* v) override; }; -class CPPNamespaceDeclaration final : public AttribDeclaration +class ExpInitializer final : public Initializer { public: + bool expandTuples; Expression* exp; - CPPNamespaceDeclaration* syntaxCopy(Dsymbol* s) override; - Scope* newScope(Scope* sc) override; - const char* toChars() const override; void accept(Visitor* v) override; - CPPNamespaceDeclaration* isCPPNamespaceDeclaration() override; }; -class VisibilityDeclaration final : public AttribDeclaration +enum class NeedInterpret +{ + INITnointerpret = 0, + INITinterpret = 1, +}; + +class StructInitializer final : public Initializer { public: - Visibility visibility; - _d_dynamicArray< Identifier* > pkg_identifiers; - VisibilityDeclaration* syntaxCopy(Dsymbol* s) override; - Scope* newScope(Scope* sc) override; - const char* kind() const override; - const char* toPrettyChars(bool __param_0_) override; - VisibilityDeclaration* isVisibilityDeclaration() override; + Array field; + Array value; void accept(Visitor* v) override; }; -class AlignDeclaration final : public AttribDeclaration +class VoidInitializer final : public Initializer { public: - Array* exps; - structalign_t salign; - AlignDeclaration* syntaxCopy(Dsymbol* s) override; - Scope* newScope(Scope* sc) override; + Type* type; void accept(Visitor* v) override; }; -class AnonDeclaration final : public AttribDeclaration +extern Initializer* initializerSemantic(Initializer* init, Scope* sc, Type*& tx, NeedInterpret needInterpret); + +extern Expression* initializerToExpression(Initializer* init, Type* itype = nullptr, const bool isCfile = false); + +enum class DotExpFlag +{ + none = 0, + gag = 1, + noDeref = 2, + noAliasThis = 4, +}; + +enum : int32_t { LOGDEFAULTINIT = 0 }; + +enum : int32_t { LOGDOTEXP = 0 }; + +enum class DiagnosticReporting : uint8_t +{ + error = 0u, + inform = 1u, + off = 2u, +}; + +enum class CppStdRevision : uint32_t +{ + cpp98 = 199711u, + cpp11 = 201103u, + cpp14 = 201402u, + cpp17 = 201703u, + cpp20 = 202002u, +}; + +struct Help final +{ + bool manual; + bool usage; + bool mcpu; + bool transition; + bool check; + bool checkAction; + bool revert; + bool preview; + bool externStd; + bool hc; + Help() : + manual(), + usage(), + mcpu(), + transition(), + check(), + checkAction(), + revert(), + preview(), + externStd(), + hc() + { + } + Help(bool manual, bool usage = false, bool mcpu = false, bool transition = false, bool check = false, bool checkAction = false, bool revert = false, bool preview = false, bool externStd = false, bool hc = false) : + manual(manual), + usage(usage), + mcpu(mcpu), + transition(transition), + check(check), + checkAction(checkAction), + revert(revert), + preview(preview), + externStd(externStd), + hc(hc) + {} +}; + +struct Verbose final +{ + bool verbose; + bool showColumns; + bool tls; + bool templates; + bool templatesListInstances; + bool gc; + bool field; + bool complex; + bool vin; + bool showGaggedErrors; + bool printErrorContext; + bool logo; + bool color; + bool cov; + MessageStyle messageStyle; + uint32_t errorLimit; + uint32_t errorSupplementLimit; + uint32_t errorSupplementCount(); + Verbose() : + verbose(), + showColumns(), + tls(), + templates(), + templatesListInstances(), + gc(), + field(), + complex(true), + vin(), + showGaggedErrors(), + printErrorContext(), + logo(), + color(), + cov(), + messageStyle((MessageStyle)0u), + errorLimit(20u), + errorSupplementLimit(6u) + { + } + Verbose(bool verbose, bool showColumns = false, bool tls = false, bool templates = false, bool templatesListInstances = false, bool gc = false, bool field = false, bool complex = true, bool vin = false, bool showGaggedErrors = false, bool printErrorContext = false, bool logo = false, bool color = false, bool cov = false, MessageStyle messageStyle = (MessageStyle)0u, uint32_t errorLimit = 20u, uint32_t errorSupplementLimit = 6u) : + verbose(verbose), + showColumns(showColumns), + tls(tls), + templates(templates), + templatesListInstances(templatesListInstances), + gc(gc), + field(field), + complex(complex), + vin(vin), + showGaggedErrors(showGaggedErrors), + printErrorContext(printErrorContext), + logo(logo), + color(color), + cov(cov), + messageStyle(messageStyle), + errorLimit(errorLimit), + errorSupplementLimit(errorSupplementLimit) + {} +}; + +enum class FeatureState : uint8_t { -public: - bool isunion; - int32_t sem; - uint32_t anonoffset; - uint32_t anonstructsize; - uint32_t anonalignsize; - AnonDeclaration* syntaxCopy(Dsymbol* s) override; - void setFieldOffset(AggregateDeclaration* ad, FieldState& fieldState, bool isunion) override; - const char* kind() const override; - AnonDeclaration* isAnonDeclaration() override; - void accept(Visitor* v) override; + default_ = 0u, + disabled = 1u, + enabled = 2u, }; -class PragmaDeclaration final : public AttribDeclaration +enum class CHECKENABLE : uint8_t { -public: - Array* args; - PragmaDeclaration* syntaxCopy(Dsymbol* s) override; - Scope* newScope(Scope* sc) override; - const char* kind() const override; - void accept(Visitor* v) override; + _default = 0u, + off = 1u, + on = 2u, + safeonly = 3u, }; -class ConditionalDeclaration : public AttribDeclaration +enum class CHECKACTION : uint8_t { -public: - Condition* condition; - Array* elsedecl; - ConditionalDeclaration* syntaxCopy(Dsymbol* s) override; - bool oneMember(Dsymbol** ps, Identifier* ident) final override; - Array* include(Scope* sc) override; - void addComment(const char* comment) final override; - void accept(Visitor* v) override; + D = 0u, + C = 1u, + halt = 2u, + context = 3u, }; -class StaticIfDeclaration final : public ConditionalDeclaration +struct Output final { -public: - ScopeDsymbol* scopesym; -private: - bool addisdone; - bool onStack; -public: - StaticIfDeclaration* syntaxCopy(Dsymbol* s) override; - Array* include(Scope* sc) override; - void importAll(Scope* sc) override; - const char* kind() const override; - StaticIfDeclaration* isStaticIfDeclaration() override; - void accept(Visitor* v) override; + bool doOutput; + bool fullOutput; + _d_dynamicArray< const char > dir; + _d_dynamicArray< const char > name; + Array files; + OutBuffer* buffer; + int32_t bufferLines; + Output() : + doOutput(), + fullOutput(), + dir(), + name(), + files(), + buffer(), + bufferLines() + { + } + Output(bool doOutput, bool fullOutput = false, _d_dynamicArray< const char > dir = {}, _d_dynamicArray< const char > name = {}, Array files = Array(), OutBuffer* buffer = nullptr, int32_t bufferLines = 0) : + doOutput(doOutput), + fullOutput(fullOutput), + dir(dir), + name(name), + files(files), + buffer(buffer), + bufferLines(bufferLines) + {} }; -class StaticForeachDeclaration final : public AttribDeclaration +enum class JsonFieldFlags : uint32_t { -public: - StaticForeach* sfe; - ScopeDsymbol* scopesym; - bool onStack; - bool cached; - Array* cache; - StaticForeachDeclaration* syntaxCopy(Dsymbol* s) override; - bool oneMember(Dsymbol** ps, Identifier* ident) override; - Array* include(Scope* sc) override; - void addComment(const char* comment) override; - void importAll(Scope* sc) override; - const char* kind() const override; - void accept(Visitor* v) override; + none = 0u, + compilerInfo = 1u, + buildInfo = 2u, + modules = 4u, + semantics = 8u, }; -class ForwardingAttribDeclaration final : public AttribDeclaration +struct Param final { -public: - ForwardingScopeDsymbol* sym; - ForwardingAttribDeclaration(Array* decl); - Scope* newScope(Scope* sc) override; - ForwardingAttribDeclaration* isForwardingAttribDeclaration() override; - void accept(Visitor* v) override; + bool obj; + bool multiobj; + bool trace; + bool tracegc; + bool vcg_ast; + DiagnosticReporting useDeprecated; + bool useUnitTests; + bool useInline; + bool release; + bool preservePaths; + DiagnosticReporting warnings; + bool cov; + uint8_t covPercent; + bool ctfe_cov; + bool ignoreUnsupportedPragmas; + bool useModuleInfo; + bool useTypeInfo; + bool useExceptions; + bool useGC; + bool betterC; + bool addMain; + bool allInst; + bool bitfields; + CppStdRevision cplusplus; + Help help; + Verbose v; + FeatureState useDIP25; + FeatureState useDIP1000; + bool ehnogc; + bool useDIP1021; + FeatureState fieldwise; + bool fixAliasThis; + FeatureState rvalueRefParam; + FeatureState noSharedAccess; + bool previewIn; + bool inclusiveInContracts; + bool shortenedMethods; + bool fixImmutableConv; + bool fix16997; + FeatureState dtorFields; + FeatureState systemVariables; + CHECKENABLE useInvariants; + CHECKENABLE useIn; + CHECKENABLE useOut; + CHECKENABLE useArrayBounds; + CHECKENABLE useAssert; + CHECKENABLE useSwitchError; + CHECKENABLE boundscheck; + CHECKACTION checkAction; + _d_dynamicArray< const char > argv0; + Array modFileAliasStrings; + Array* imppath; + Array* fileImppath; + _d_dynamicArray< const char > objdir; + _d_dynamicArray< const char > objname; + _d_dynamicArray< const char > libname; + Output ddoc; + Output dihdr; + Output cxxhdr; + Output json; + JsonFieldFlags jsonFieldFlags; + Output makeDeps; + Output mixinOut; + Output moduleDeps; + uint32_t debuglevel; + uint32_t versionlevel; + bool run; + Array runargs; + Array cppswitches; + const char* cpp; + Array objfiles; + Array linkswitches; + Array linkswitchIsForCC; + Array libfiles; + Array dllfiles; + _d_dynamicArray< const char > deffile; + _d_dynamicArray< const char > resfile; + _d_dynamicArray< const char > exefile; + _d_dynamicArray< const char > mapfile; + bool parsingUnittestsRequired(); + Param() : + obj(true), + multiobj(), + trace(), + tracegc(), + vcg_ast(), + useDeprecated((DiagnosticReporting)1u), + useUnitTests(), + useInline(false), + release(), + preservePaths(), + warnings((DiagnosticReporting)2u), + cov(), + covPercent(), + ctfe_cov(false), + ignoreUnsupportedPragmas(true), + useModuleInfo(true), + useTypeInfo(true), + useExceptions(true), + useGC(true), + betterC(), + addMain(), + allInst(), + bitfields(), + cplusplus((CppStdRevision)201103u), + help(), + v(), + useDIP25((FeatureState)2u), + ehnogc(), + useDIP1021(), + fixAliasThis(), + previewIn(), + inclusiveInContracts(), + shortenedMethods(true), + fixImmutableConv(), + fix16997(true), + useInvariants((CHECKENABLE)0u), + useIn((CHECKENABLE)0u), + useOut((CHECKENABLE)0u), + useArrayBounds((CHECKENABLE)0u), + useAssert((CHECKENABLE)0u), + useSwitchError((CHECKENABLE)0u), + boundscheck((CHECKENABLE)0u), + checkAction((CHECKACTION)0u), + argv0(), + modFileAliasStrings(), + imppath(), + fileImppath(), + objdir(), + objname(), + libname(), + ddoc(), + dihdr(), + cxxhdr(), + json(), + makeDeps(), + mixinOut(), + moduleDeps(), + debuglevel(), + versionlevel(), + run(), + runargs(), + cppswitches(), + cpp(), + objfiles(), + linkswitches(), + linkswitchIsForCC(), + libfiles(), + dllfiles(), + deffile(), + resfile(), + exefile(), + mapfile() + { + } + Param(bool obj, bool multiobj = false, bool trace = false, bool tracegc = false, bool vcg_ast = false, DiagnosticReporting useDeprecated = (DiagnosticReporting)1u, bool useUnitTests = false, bool useInline = false, bool release = false, bool preservePaths = false, DiagnosticReporting warnings = (DiagnosticReporting)2u, bool cov = false, uint8_t covPercent = 0u, bool ctfe_cov = false, bool ignoreUnsupportedPragmas = true, bool useModuleInfo = true, bool useTypeInfo = true, bool useExceptions = true, bool useGC = true, bool betterC = false, bool addMain = false, bool allInst = false, bool bitfields = false, CppStdRevision cplusplus = (CppStdRevision)201103u, Help help = Help(), Verbose v = Verbose(), FeatureState useDIP25 = (FeatureState)2u, FeatureState useDIP1000 = (FeatureState)0u, bool ehnogc = false, bool useDIP1021 = false, FeatureState fieldwise = (FeatureState)0u, bool fixAliasThis = false, FeatureState rvalueRefParam = (FeatureState)0u, FeatureState noSharedAccess = (FeatureState)0u, bool previewIn = false, bool inclusiveInContracts = false, bool shortenedMethods = true, bool fixImmutableConv = false, bool fix16997 = true, FeatureState dtorFields = (FeatureState)0u, FeatureState systemVariables = (FeatureState)0u, CHECKENABLE useInvariants = (CHECKENABLE)0u, CHECKENABLE useIn = (CHECKENABLE)0u, CHECKENABLE useOut = (CHECKENABLE)0u, CHECKENABLE useArrayBounds = (CHECKENABLE)0u, CHECKENABLE useAssert = (CHECKENABLE)0u, CHECKENABLE useSwitchError = (CHECKENABLE)0u, CHECKENABLE boundscheck = (CHECKENABLE)0u, CHECKACTION checkAction = (CHECKACTION)0u, _d_dynamicArray< const char > argv0 = {}, Array modFileAliasStrings = Array(), Array* imppath = nullptr, Array* fileImppath = nullptr, _d_dynamicArray< const char > objdir = {}, _d_dynamicArray< const char > objname = {}, _d_dynamicArray< const char > libname = {}, Output ddoc = Output(), Output dihdr = Output(), Output cxxhdr = Output(), Output json = Output(), JsonFieldFlags jsonFieldFlags = (JsonFieldFlags)0u, Output makeDeps = Output(), Output mixinOut = Output(), Output moduleDeps = Output(), uint32_t debuglevel = 0u, uint32_t versionlevel = 0u, bool run = false, Array runargs = Array(), Array cppswitches = Array(), const char* cpp = nullptr, Array objfiles = Array(), Array linkswitches = Array(), Array linkswitchIsForCC = Array(), Array libfiles = Array(), Array dllfiles = Array(), _d_dynamicArray< const char > deffile = {}, _d_dynamicArray< const char > resfile = {}, _d_dynamicArray< const char > exefile = {}, _d_dynamicArray< const char > mapfile = {}) : + obj(obj), + multiobj(multiobj), + trace(trace), + tracegc(tracegc), + vcg_ast(vcg_ast), + useDeprecated(useDeprecated), + useUnitTests(useUnitTests), + useInline(useInline), + release(release), + preservePaths(preservePaths), + warnings(warnings), + cov(cov), + covPercent(covPercent), + ctfe_cov(ctfe_cov), + ignoreUnsupportedPragmas(ignoreUnsupportedPragmas), + useModuleInfo(useModuleInfo), + useTypeInfo(useTypeInfo), + useExceptions(useExceptions), + useGC(useGC), + betterC(betterC), + addMain(addMain), + allInst(allInst), + bitfields(bitfields), + cplusplus(cplusplus), + help(help), + v(v), + useDIP25(useDIP25), + useDIP1000(useDIP1000), + ehnogc(ehnogc), + useDIP1021(useDIP1021), + fieldwise(fieldwise), + fixAliasThis(fixAliasThis), + rvalueRefParam(rvalueRefParam), + noSharedAccess(noSharedAccess), + previewIn(previewIn), + inclusiveInContracts(inclusiveInContracts), + shortenedMethods(shortenedMethods), + fixImmutableConv(fixImmutableConv), + fix16997(fix16997), + dtorFields(dtorFields), + systemVariables(systemVariables), + useInvariants(useInvariants), + useIn(useIn), + useOut(useOut), + useArrayBounds(useArrayBounds), + useAssert(useAssert), + useSwitchError(useSwitchError), + boundscheck(boundscheck), + checkAction(checkAction), + argv0(argv0), + modFileAliasStrings(modFileAliasStrings), + imppath(imppath), + fileImppath(fileImppath), + objdir(objdir), + objname(objname), + libname(libname), + ddoc(ddoc), + dihdr(dihdr), + cxxhdr(cxxhdr), + json(json), + jsonFieldFlags(jsonFieldFlags), + makeDeps(makeDeps), + mixinOut(mixinOut), + moduleDeps(moduleDeps), + debuglevel(debuglevel), + versionlevel(versionlevel), + run(run), + runargs(runargs), + cppswitches(cppswitches), + cpp(cpp), + objfiles(objfiles), + linkswitches(linkswitches), + linkswitchIsForCC(linkswitchIsForCC), + libfiles(libfiles), + dllfiles(dllfiles), + deffile(deffile), + resfile(resfile), + exefile(exefile), + mapfile(mapfile) + {} }; -class MixinDeclaration final : public AttribDeclaration +struct CompileEnv final { -public: - Array* exps; - ScopeDsymbol* scopesym; - bool compiled; - MixinDeclaration* syntaxCopy(Dsymbol* s) override; - const char* kind() const override; - MixinDeclaration* isMixinDeclaration() override; - void accept(Visitor* v) override; + uint32_t versionNumber; + _d_dynamicArray< const char > date; + _d_dynamicArray< const char > time; + _d_dynamicArray< const char > vendor; + _d_dynamicArray< const char > timestamp; + bool previewIn; + bool ddocOutput; + bool masm; + CompileEnv() : + versionNumber(), + date(), + time(), + vendor(), + timestamp(), + previewIn(), + ddocOutput(), + masm() + { + } + CompileEnv(uint32_t versionNumber, _d_dynamicArray< const char > date = {}, _d_dynamicArray< const char > time = {}, _d_dynamicArray< const char > vendor = {}, _d_dynamicArray< const char > timestamp = {}, bool previewIn = false, bool ddocOutput = false, bool masm = false) : + versionNumber(versionNumber), + date(date), + time(time), + vendor(vendor), + timestamp(timestamp), + previewIn(previewIn), + ddocOutput(ddocOutput), + masm(masm) + {} }; -class UserAttributeDeclaration final : public AttribDeclaration +struct Global final { -public: - Array* atts; - UserAttributeDeclaration* syntaxCopy(Dsymbol* s) override; - Scope* newScope(Scope* sc) override; - Array* getAttributes(); - const char* kind() const override; - void accept(Visitor* v) override; - static bool isGNUABITag(Expression* e); - static void checkGNUABITag(Dsymbol* sym, LINK linkage); -}; - -extern BUILTIN isBuiltin(FuncDeclaration* fd); - -extern Expression* eval_builtin(const Loc& loc, FuncDeclaration* fd, Array* arguments); - -extern bool includeImports; - -extern Array includeModulePatterns; - -extern Array compiledImports; + _d_dynamicArray< const char > inifilename; + _d_dynamicArray< const char > copyright; + _d_dynamicArray< const char > written; + Array* path; + Array* filePath; + char datetime[26LLU]; + CompileEnv compileEnv; + Param params; + uint32_t errors; + uint32_t warnings; + uint32_t gag; + uint32_t gaggedErrors; + uint32_t gaggedWarnings; + void* console; + Array* versionids; + Array* debugids; + bool hasMainFunction; + uint32_t varSequenceNumber; + FileManager* fileManager; + enum : int32_t { recursionLimit = 500 }; -struct Compiler final -{ - static Expression* paintAsType(UnionExp* pue, Expression* e, Type* type); - static void onParseModule(Module* m); - static bool onImport(Module* m); - Compiler() + ErrorSink* errorSink; + ErrorSink* errorSinkNull; + FileName(*preprocess)(FileName , const Loc& , bool& , OutBuffer* ); + uint32_t startGagging(); + bool endGagging(uint32_t oldGagged); + void increaseErrorCount(); + void _init(); + uint32_t versionNumber(); + const char* const versionChars(); + Global() : + inifilename(), + copyright(73, "Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved"), + written(24, "written by Walter Bright"), + path(), + filePath(), + compileEnv(), + params(), + errors(), + warnings(), + gag(), + gaggedErrors(), + gaggedWarnings(), + console(), + versionids(), + debugids(), + hasMainFunction(), + varSequenceNumber(1u), + fileManager(), + errorSink(), + errorSinkNull(), + preprocess() { } + Global(_d_dynamicArray< const char > inifilename, _d_dynamicArray< const char > copyright = { 73, "Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved" }, _d_dynamicArray< const char > written = { 24, "written by Walter Bright" }, Array* path = nullptr, Array* filePath = nullptr, CompileEnv compileEnv = CompileEnv(), Param params = Param(), uint32_t errors = 0u, uint32_t warnings = 0u, uint32_t gag = 0u, uint32_t gaggedErrors = 0u, uint32_t gaggedWarnings = 0u, void* console = nullptr, Array* versionids = nullptr, Array* debugids = nullptr, bool hasMainFunction = false, uint32_t varSequenceNumber = 1u, FileManager* fileManager = nullptr, ErrorSink* errorSink = nullptr, ErrorSink* errorSinkNull = nullptr, FileName(*preprocess)(FileName , const Loc& , bool& , OutBuffer* ) = nullptr) : + inifilename(inifilename), + copyright(copyright), + written(written), + path(path), + filePath(filePath), + compileEnv(compileEnv), + params(params), + errors(errors), + warnings(warnings), + gag(gag), + gaggedErrors(gaggedErrors), + gaggedWarnings(gaggedWarnings), + console(console), + versionids(versionids), + debugids(debugids), + hasMainFunction(hasMainFunction), + varSequenceNumber(varSequenceNumber), + fileManager(fileManager), + errorSink(errorSink), + errorSinkNull(errorSinkNull), + preprocess(preprocess) + {} }; -class Condition : public ASTNode -{ -public: - Loc loc; - Include inc; - DYNCAST dyncast() const final override; - virtual Condition* syntaxCopy() = 0; - virtual int32_t include(Scope* sc) = 0; - virtual DebugCondition* isDebugCondition(); - virtual VersionCondition* isVersionCondition(); - virtual StaticIfCondition* isStaticIfCondition(); - void accept(Visitor* v) override; -}; - -class StaticForeach final : public RootObject -{ -public: - Loc loc; - ForeachStatement* aggrfe; - ForeachRangeStatement* rangefe; - bool needExpansion; -}; +extern Global global; -class DVCondition : public Condition +class Parameter final : public ASTNode { public: - uint32_t level; + Loc loc; + StorageClass storageClass; + Type* type; Identifier* ident; - Module* mod; - DVCondition* syntaxCopy() final override; - void accept(Visitor* v) override; -}; - -class DebugCondition final : public DVCondition -{ -public: - static void addGlobalIdent(const char* ident); - int32_t include(Scope* sc) override; - DebugCondition* isDebugCondition() override; - void accept(Visitor* v) override; - const char* toChars() const override; -}; - -class VersionCondition final : public DVCondition -{ -public: - static void addGlobalIdent(const char* ident); - static void addPredefinedGlobalIdent(const char* ident); - int32_t include(Scope* sc) override; - VersionCondition* isVersionCondition() override; + Expression* defaultArg; + UserAttributeDeclaration* userAttribDecl; + static Parameter* create(const Loc& loc, StorageClass storageClass, Type* type, Identifier* ident, Expression* defaultArg, UserAttributeDeclaration* userAttribDecl); + Parameter* syntaxCopy(); + Type* isLazyArray(); + bool isLazy() const; + bool isReference() const; + DYNCAST dyncast() const override; void accept(Visitor* v) override; + static size_t dim(Array* parameters); + static Parameter* getNth(Array* parameters, size_t nth); const char* toChars() const override; + bool isCovariant(bool returnByRef, const Parameter* const p, bool previewIn = global.params.previewIn) const; }; -class StaticIfCondition final : public Condition +enum class RET { -public: - Expression* exp; - StaticIfCondition* syntaxCopy() override; - int32_t include(Scope* sc) override; - void accept(Visitor* v) override; - StaticIfCondition* isStaticIfCondition() override; - const char* toChars() const override; + regs = 1, + stack = 2, }; -extern const char* toCppMangleItanium(Dsymbol* s); - -extern const char* cppTypeInfoMangleItanium(Dsymbol* s); - -extern const char* cppThunkMangleItanium(FuncDeclaration* fd, int32_t offset); - -extern const char* toCppMangleMSVC(Dsymbol* s); - -extern const char* cppTypeInfoMangleMSVC(Dsymbol* s); - -extern const char* toCppMangleDMC(Dsymbol* s); - -extern const char* cppTypeInfoMangleDMC(Dsymbol* s); - -extern FileName preprocess(FileName csrcfile, const Loc& loc, bool& ifile, OutBuffer* defines); - -extern MATCH implicitConvTo(Expression* e, Type* t); +enum : uint64_t { SIZE_INVALID = 18446744073709551615LLU }; -struct BaseClass final +enum class ScopeRef { - Type* type; - ClassDeclaration* sym; - uint32_t offset; - Array vtbl; - _d_dynamicArray< BaseClass > baseInterfaces; - bool fillVtbl(ClassDeclaration* cd, Array* vtbl, int32_t newinstance); - BaseClass() : - type(), - sym(), - offset(), - vtbl(), - baseInterfaces() - { - } + None = 0, + Scope = 1, + ReturnScope = 2, + Ref = 3, + ReturnRef = 4, + RefScope = 5, + ReturnRef_Scope = 6, + Ref_ReturnScope = 7, + Return = 8, }; -class ClassDeclaration : public AggregateDeclaration +enum class TRUSTformat { -public: - static ClassDeclaration* object; - static ClassDeclaration* throwable; - static ClassDeclaration* exception; - static ClassDeclaration* errorException; - static ClassDeclaration* cpp_type_info_ptr; - ClassDeclaration* baseClass; - FuncDeclaration* staticCtor; - FuncDeclaration* staticDtor; - Array vtbl; - Array vtblFinal; - Array* baseclasses; - _d_dynamicArray< BaseClass* > interfaces; - Array* vtblInterfaces; - TypeInfoClassDeclaration* vclassinfo; - bool com; - bool stack; - int32_t cppDtorVtblIndex; - bool inuse; - ThreeState isabstract; - Baseok baseok; - ObjcClassDeclaration objc; - Symbol* cpp_type_info_ptr_sym; - static ClassDeclaration* create(const Loc& loc, Identifier* id, Array* baseclasses, Array* members, bool inObject); - const char* toPrettyChars(bool qualifyTypes = false) override; - ClassDeclaration* syntaxCopy(Dsymbol* s) override; - Scope* newScope(Scope* sc) override; - enum : int32_t { OFFSET_RUNTIME = 1985229328 }; - - enum : int32_t { OFFSET_FWDREF = 1985229329 }; - - virtual bool isBaseOf(ClassDeclaration* cd, int32_t* poffset); - bool isBaseInfoComplete() const; - void finalizeSize() final override; - bool hasMonitor(); - bool isFuncHidden(FuncDeclaration* fd); - bool isCOMclass() const; - virtual bool isCOMinterface() const; - bool isCPPclass() const; - virtual bool isCPPinterface() const; - bool isAbstract(); - virtual int32_t vtblOffset() const; - const char* kind() const override; - void addObjcSymbols(Array* classes, Array* categories) final override; - Dsymbol* vtblsym; - Dsymbol* vtblSymbol(); - ClassDeclaration* isClassDeclaration() final override; - void accept(Visitor* v) override; + TRUSTformatDefault = 0, + TRUSTformatSystem = 1, }; -class InterfaceDeclaration final : public ClassDeclaration +class TypeNext : public Type { public: - InterfaceDeclaration* syntaxCopy(Dsymbol* s) override; - Scope* newScope(Scope* sc) override; - bool isBaseOf(ClassDeclaration* cd, int32_t* poffset) override; - const char* kind() const override; - int32_t vtblOffset() const override; - bool isCPPinterface() const override; - bool isCOMinterface() const override; - InterfaceDeclaration* isInterfaceDeclaration() override; + Type* next; + void checkDeprecated(const Loc& loc, Scope* sc) final override; + int32_t hasWild() const final override; + Type* nextOf() final override; + Type* makeConst() final override; + Type* makeImmutable() final override; + Type* makeShared() final override; + Type* makeSharedConst() final override; + Type* makeWild() final override; + Type* makeWildConst() final override; + Type* makeSharedWild() final override; + Type* makeSharedWildConst() final override; + Type* makeMutable() final override; + MATCH constConv(Type* to) override; + uint8_t deduceWild(Type* t, bool isRef) final override; + void transitive(); void accept(Visitor* v) override; }; -extern void ObjectNotFound(Identifier* id); - -class Declaration : public Dsymbol +class TypeArray : public TypeNext { public: - Type* type; - Type* originalType; - StorageClass storage_class; - Visibility visibility; - LINK _linkage; - int16_t inuse; - uint8_t adFlags; - enum : int32_t { wasRead = 1 }; - - enum : int32_t { ignoreRead = 2 }; - - enum : int32_t { nounderscore = 4 }; - - enum : int32_t { hidden = 8 }; - - Symbol* isym; - _d_dynamicArray< const char > mangleOverride; - const char* kind() const override; - uinteger_t size(const Loc& loc) final override; - bool isStatic() const; - LINK resolvedLinkage() const; - virtual bool isDelete(); - virtual bool isDataseg(); - virtual bool isThreadlocal(); - virtual bool isCodeseg() const; - bool isFinal() const; - virtual bool isAbstract(); - bool isConst() const; - bool isImmutable() const; - bool isWild() const; - bool isAuto() const; - bool isScope() const; - bool isReturn() const; - bool isSynchronized() const; - bool isParameter() const; - bool isDeprecated() const final override; - bool isDisabled() const; - bool isOverride() const; - bool isResult() const; - bool isField() const; - bool isIn() const; - bool isOut() const; - bool isRef() const; - bool isReference() const; - bool isFuture() const; - Visibility visible() final override; - Declaration* isDeclaration() final override; void accept(Visitor* v) override; }; -class TupleDeclaration final : public Declaration +class TypeAArray final : public TypeArray { public: - Array* objects; - TypeTuple* tupletype; - bool isexp; - bool building; - TupleDeclaration* syntaxCopy(Dsymbol* s) override; + Type* index; + Loc loc; + static TypeAArray* create(Type* t, Type* index); const char* kind() const override; - Type* getType() override; - Dsymbol* toAlias2() override; - bool needThis() override; - TupleDeclaration* isTupleDeclaration() override; + TypeAArray* syntaxCopy() override; + uinteger_t size(const Loc& loc) override; + bool isZeroInit(const Loc& loc) override; + bool isBoolean() override; + bool hasPointers() override; + MATCH implicitConvTo(Type* to) override; + MATCH constConv(Type* to) override; void accept(Visitor* v) override; }; -class AliasDeclaration final : public Declaration +class TypeBasic final : public Type { public: - Dsymbol* aliassym; - Dsymbol* overnext; - Dsymbol* _import_; - static AliasDeclaration* create(const Loc& loc, Identifier* id, Type* type); - AliasDeclaration* syntaxCopy(Dsymbol* s) override; - bool overloadInsert(Dsymbol* s) override; + const char* dstring; + uint32_t flags; const char* kind() const override; - Type* getType() override; - Dsymbol* toAlias() override; - Dsymbol* toAlias2() override; - bool isOverloadable() const override; - AliasDeclaration* isAliasDeclaration() override; + TypeBasic* syntaxCopy() override; + uinteger_t size(const Loc& loc) override; + uint32_t alignsize() override; + bool isintegral() override; + bool isfloating() override; + bool isreal() override; + bool isimaginary() override; + bool iscomplex() override; + bool isscalar() override; + bool isunsigned() override; + MATCH implicitConvTo(Type* to) override; + bool isZeroInit(const Loc& loc) override; + TypeBasic* isTypeBasic() override; void accept(Visitor* v) override; }; -class OverDeclaration final : public Declaration +enum class AliasThisRec +{ + no = 0, + yes = 1, + fwdref = 2, + typeMask = 3, + tracing = 4, + tracingDT = 8, +}; + +class TypeClass final : public Type { public: - Dsymbol* overnext; - Dsymbol* aliassym; + ClassDeclaration* sym; + AliasThisRec att; + CPPMANGLE cppmangle; const char* kind() const override; - bool equals(const RootObject* const o) const override; - bool overloadInsert(Dsymbol* s) override; - bool isOverloadable() const override; - Dsymbol* isUnique(); - OverDeclaration* isOverDeclaration() override; + uinteger_t size(const Loc& loc) override; + TypeClass* syntaxCopy() override; + Dsymbol* toDsymbol(Scope* sc) override; + ClassDeclaration* isClassHandle() override; + bool isBaseOf(Type* t, int32_t* poffset) override; + MATCH implicitConvTo(Type* to) override; + MATCH constConv(Type* to) override; + uint8_t deduceWild(Type* t, bool isRef) override; + Type* toHeadMutable() override; + bool isZeroInit(const Loc& loc) override; + bool isscope() override; + bool isBoolean() override; + bool hasPointers() override; void accept(Visitor* v) override; }; -class VarDeclaration : public Declaration +class TypeDArray final : public TypeArray { public: - Initializer* _init; - Array nestedrefs; - TupleDeclaration* aliasTuple; - VarDeclaration* lastVar; - Expression* edtor; - IntRange* range; - Array* maybes; - uint32_t endlinnum; - uint32_t offset; - uint32_t sequenceNumber; - structalign_t alignment; - enum : uint32_t { AdrOnStackNone = 4294967295u }; - - uint32_t ctfeAdrOnStack; - bool isargptr() const; - bool isargptr(bool v); - bool ctorinit() const; - bool ctorinit(bool v); - bool iscatchvar() const; - bool iscatchvar(bool v); - bool isowner() const; - bool isowner(bool v); - bool setInCtorOnly() const; - bool setInCtorOnly(bool v); - bool onstack() const; - bool onstack(bool v); - bool overlapped() const; - bool overlapped(bool v); - bool overlapUnsafe() const; - bool overlapUnsafe(bool v); - bool maybeScope() const; - bool maybeScope(bool v); - bool doNotInferReturn() const; - bool doNotInferReturn(bool v); - bool isArgDtorVar() const; - bool isArgDtorVar(bool v); - bool isCmacro() const; - bool isCmacro(bool v); - bool dllImport() const; - bool dllImport(bool v); - bool dllExport() const; - bool dllExport(bool v); - bool inClosure() const; - bool inClosure(bool v); - bool inAlignSection() const; - bool inAlignSection(bool v); - bool systemInferred() const; - bool systemInferred(bool v); -private: - uint32_t bitFields; -public: - int8_t canassign; - uint8_t isdataseg; - static VarDeclaration* create(const Loc& loc, Type* type, Identifier* ident, Initializer* _init, StorageClass storage_class = static_cast(STC::undefined_)); - VarDeclaration* syntaxCopy(Dsymbol* s) override; - void setFieldOffset(AggregateDeclaration* ad, FieldState& fieldState, bool isunion) override; const char* kind() const override; - AggregateDeclaration* isThis() final override; - bool needThis() final override; - bool isExport() const final override; - bool isImportedSymbol() const final override; - bool isCtorinit() const; - bool isDataseg() final override; - bool isThreadlocal() final override; - bool isCTFE(); - bool isOverlappedWith(VarDeclaration* v); - bool hasPointers() final override; - bool canTakeAddressOf(); - bool needsScopeDtor(); - void checkCtorConstInit() final override; - Dsymbol* toAlias() final override; - VarDeclaration* isVarDeclaration() final override; + TypeDArray* syntaxCopy() override; + uinteger_t size(const Loc& loc) override; + uint32_t alignsize() override; + bool isString() override; + bool isZeroInit(const Loc& loc) override; + bool isBoolean() override; + MATCH implicitConvTo(Type* to) override; + bool hasPointers() override; void accept(Visitor* v) override; }; -class BitFieldDeclaration : public VarDeclaration +class TypeDelegate final : public TypeNext { public: - Expression* width; - uint32_t fieldWidth; - uint32_t bitOffset; - BitFieldDeclaration* syntaxCopy(Dsymbol* s) override; - BitFieldDeclaration* isBitFieldDeclaration() final override; + static TypeDelegate* create(TypeFunction* t); + const char* kind() const override; + TypeDelegate* syntaxCopy() override; + Type* addStorageClass(StorageClass stc) override; + uinteger_t size(const Loc& loc) override; + uint32_t alignsize() override; + MATCH implicitConvTo(Type* to) override; + bool isZeroInit(const Loc& loc) override; + bool isBoolean() override; + bool hasPointers() override; void accept(Visitor* v) override; - uint64_t getMinMax(Identifier* id); - void setFieldOffset(AggregateDeclaration* ad, FieldState& fieldState, bool isunion) final override; }; -class SymbolDeclaration final : public Declaration +class TypeEnum final : public Type { public: - AggregateDeclaration* dsym; - SymbolDeclaration* isSymbolDeclaration() override; + EnumDeclaration* sym; + const char* kind() const override; + TypeEnum* syntaxCopy() override; + uinteger_t size(const Loc& loc) override; + Type* memType(const Loc& loc = Loc::initial); + uint32_t alignsize() override; + Dsymbol* toDsymbol(Scope* sc) override; + bool isintegral() override; + bool isfloating() override; + bool isreal() override; + bool isimaginary() override; + bool iscomplex() override; + bool isscalar() override; + bool isunsigned() override; + bool isBoolean() override; + bool isString() override; + bool isAssignable() override; + bool needsDestruction() override; + bool needsCopyOrPostblit() override; + bool needsNested() override; + MATCH implicitConvTo(Type* to) override; + MATCH constConv(Type* to) override; + bool isZeroInit(const Loc& loc) override; + bool hasPointers() override; + bool hasVoidInitPointers() override; + bool hasSystemFields() override; + bool hasInvariant() override; + Type* nextOf() override; void accept(Visitor* v) override; }; -class TypeInfoDeclaration : public VarDeclaration +class TypeError final : public Type { public: - Type* tinfo; - static TypeInfoDeclaration* create(Type* tinfo); - TypeInfoDeclaration* syntaxCopy(Dsymbol* s) final override; - const char* toChars() const final override; - TypeInfoDeclaration* isTypeInfoDeclaration() final override; + const char* kind() const override; + TypeError* syntaxCopy() override; + uinteger_t size(const Loc& loc) override; + Expression* defaultInitLiteral(const Loc& loc) override; void accept(Visitor* v) override; }; -class TypeInfoStructDeclaration final : public TypeInfoDeclaration +enum class TRUST : uint8_t { -public: - static TypeInfoStructDeclaration* create(Type* tinfo); - void accept(Visitor* v) override; + default_ = 0u, + system = 1u, + trusted = 2u, + safe = 3u, }; -class TypeInfoClassDeclaration final : public TypeInfoDeclaration +class TypeFunction final : public TypeNext { public: - static TypeInfoClassDeclaration* create(Type* tinfo); - void accept(Visitor* v) override; -}; + ParameterList parameterList; +private: + struct BitFields final + { + bool isnothrow; + bool isnogc; + bool isproperty; + bool isref; + bool isreturn; + bool isScopeQual; + bool isreturninferred; + bool isscopeinferred; + bool islive; + bool incomplete; + bool isInOutParam; + bool isInOutQual; + bool isctor; + bool isreturnscope; + BitFields() : + isnothrow(), + isnogc(), + isproperty(), + isref(), + isreturn(), + isScopeQual(), + isreturninferred(), + isscopeinferred(), + islive(), + incomplete(), + isInOutParam(), + isInOutQual(), + isctor(), + isreturnscope() + { + } + BitFields(bool isnothrow, bool isnogc = false, bool isproperty = false, bool isref = false, bool isreturn = false, bool isScopeQual = false, bool isreturninferred = false, bool isscopeinferred = false, bool islive = false, bool incomplete = false, bool isInOutParam = false, bool isInOutQual = false, bool isctor = false, bool isreturnscope = false) : + isnothrow(isnothrow), + isnogc(isnogc), + isproperty(isproperty), + isref(isref), + isreturn(isreturn), + isScopeQual(isScopeQual), + isreturninferred(isreturninferred), + isscopeinferred(isscopeinferred), + islive(islive), + incomplete(incomplete), + isInOutParam(isInOutParam), + isInOutQual(isInOutQual), + isctor(isctor), + isreturnscope(isreturnscope) + {} + }; -class TypeInfoInterfaceDeclaration final : public TypeInfoDeclaration -{ public: - static TypeInfoInterfaceDeclaration* create(Type* tinfo); - void accept(Visitor* v) override; -}; - -class TypeInfoPointerDeclaration final : public TypeInfoDeclaration -{ + bool isnothrow() const; + bool isnothrow(bool v); + bool isnogc() const; + bool isnogc(bool v); + bool isproperty() const; + bool isproperty(bool v); + bool isref() const; + bool isref(bool v); + bool isreturn() const; + bool isreturn(bool v); + bool isScopeQual() const; + bool isScopeQual(bool v); + bool isreturninferred() const; + bool isreturninferred(bool v); + bool isscopeinferred() const; + bool isscopeinferred(bool v); + bool islive() const; + bool islive(bool v); + bool incomplete() const; + bool incomplete(bool v); + bool isInOutParam() const; + bool isInOutParam(bool v); + bool isInOutQual() const; + bool isInOutQual(bool v); + bool isctor() const; + bool isctor(bool v); + bool isreturnscope() const; + bool isreturnscope(bool v); +private: + uint16_t bitFields; public: - static TypeInfoPointerDeclaration* create(Type* tinfo); + LINK linkage; + TRUST trust; + PURE purity; + int8_t inuse; + Array* fargs; + static TypeFunction* create(Array* parameters, Type* treturn, uint8_t varargs, LINK linkage, StorageClass stc = 0); + const char* kind() const override; + TypeFunction* syntaxCopy() override; + void purityLevel(); + bool hasLazyParameters(); + bool isDstyleVariadic() const; + StorageClass parameterStorageClass(Type* tthis, Parameter* p, Array* outerVars = nullptr, bool indirect = false); + Type* addStorageClass(StorageClass stc) override; + Type* substWildTo(uint32_t __param_0_) override; + MATCH constConv(Type* to) override; + bool iswild() const; void accept(Visitor* v) override; }; -class TypeInfoArrayDeclaration final : public TypeInfoDeclaration +class TypeQualified : public Type { public: - static TypeInfoArrayDeclaration* create(Type* tinfo); + Loc loc; + Array idents; + TypeQualified* syntaxCopy() override = 0; + uinteger_t size(const Loc& loc) override; void accept(Visitor* v) override; }; -class TypeInfoStaticArrayDeclaration final : public TypeInfoDeclaration +class TypeIdentifier final : public TypeQualified { public: - static TypeInfoStaticArrayDeclaration* create(Type* tinfo); + Identifier* ident; + Dsymbol* originalSymbol; + static TypeIdentifier* create(const Loc& loc, Identifier* ident); + const char* kind() const override; + TypeIdentifier* syntaxCopy() override; + Dsymbol* toDsymbol(Scope* sc) override; void accept(Visitor* v) override; }; -class TypeInfoAssociativeArrayDeclaration final : public TypeInfoDeclaration +class TypeInstance final : public TypeQualified { public: - static TypeInfoAssociativeArrayDeclaration* create(Type* tinfo); + TemplateInstance* tempinst; + const char* kind() const override; + TypeInstance* syntaxCopy() override; + Dsymbol* toDsymbol(Scope* sc) override; void accept(Visitor* v) override; }; -class TypeInfoEnumDeclaration final : public TypeInfoDeclaration +class TypeMixin final : public Type { public: - static TypeInfoEnumDeclaration* create(Type* tinfo); + Loc loc; + Array* exps; + RootObject* obj; + const char* kind() const override; + TypeMixin* syntaxCopy() override; + Dsymbol* toDsymbol(Scope* sc) override; void accept(Visitor* v) override; }; -class TypeInfoFunctionDeclaration final : public TypeInfoDeclaration +class TypeNoreturn final : public Type { public: - static TypeInfoFunctionDeclaration* create(Type* tinfo); + const char* kind() const override; + TypeNoreturn* syntaxCopy() override; + MATCH implicitConvTo(Type* to) override; + MATCH constConv(Type* to) override; + bool isBoolean() override; + uinteger_t size(const Loc& loc) override; + uint32_t alignsize() override; void accept(Visitor* v) override; }; -class TypeInfoDelegateDeclaration final : public TypeInfoDeclaration +class TypeNull final : public Type { public: - static TypeInfoDelegateDeclaration* create(Type* tinfo); + const char* kind() const override; + TypeNull* syntaxCopy() override; + MATCH implicitConvTo(Type* to) override; + bool hasPointers() override; + bool isBoolean() override; + uinteger_t size(const Loc& loc) override; void accept(Visitor* v) override; }; -class TypeInfoTupleDeclaration final : public TypeInfoDeclaration +class TypePointer final : public TypeNext { public: - static TypeInfoTupleDeclaration* create(Type* tinfo); + static TypePointer* create(Type* t); + const char* kind() const override; + TypePointer* syntaxCopy() override; + uinteger_t size(const Loc& loc) override; + MATCH implicitConvTo(Type* to) override; + MATCH constConv(Type* to) override; + bool isscalar() override; + bool isZeroInit(const Loc& loc) override; + bool hasPointers() override; void accept(Visitor* v) override; }; -class TypeInfoConstDeclaration final : public TypeInfoDeclaration +class TypeReference final : public TypeNext { public: - static TypeInfoConstDeclaration* create(Type* tinfo); + const char* kind() const override; + TypeReference* syntaxCopy() override; + uinteger_t size(const Loc& loc) override; + bool isZeroInit(const Loc& loc) override; void accept(Visitor* v) override; }; -class TypeInfoInvariantDeclaration final : public TypeInfoDeclaration +class TypeReturn final : public TypeQualified { public: - static TypeInfoInvariantDeclaration* create(Type* tinfo); + const char* kind() const override; + TypeReturn* syntaxCopy() override; + Dsymbol* toDsymbol(Scope* sc) override; void accept(Visitor* v) override; }; -class TypeInfoSharedDeclaration final : public TypeInfoDeclaration +class TypeSArray final : public TypeArray { public: - static TypeInfoSharedDeclaration* create(Type* tinfo); + Expression* dim; + const char* kind() const override; + TypeSArray* syntaxCopy() override; + bool isIncomplete(); + uinteger_t size(const Loc& loc) override; + uint32_t alignsize() override; + bool isString() override; + bool isZeroInit(const Loc& loc) override; + structalign_t alignment() override; + MATCH constConv(Type* to) override; + MATCH implicitConvTo(Type* to) override; + Expression* defaultInitLiteral(const Loc& loc) override; + bool hasPointers() override; + bool hasSystemFields() override; + bool hasVoidInitPointers() override; + bool hasInvariant() override; + bool needsDestruction() override; + bool needsCopyOrPostblit() override; + bool needsNested() override; void accept(Visitor* v) override; }; -class TypeInfoWildDeclaration final : public TypeInfoDeclaration +class TypeSlice final : public TypeNext { public: - static TypeInfoWildDeclaration* create(Type* tinfo); + Expression* lwr; + Expression* upr; + const char* kind() const override; + TypeSlice* syntaxCopy() override; void accept(Visitor* v) override; }; -class TypeInfoVectorDeclaration final : public TypeInfoDeclaration +class TypeStruct final : public Type { public: - static TypeInfoVectorDeclaration* create(Type* tinfo); + StructDeclaration* sym; + AliasThisRec att; + bool inuse; + static TypeStruct* create(StructDeclaration* sym); + const char* kind() const override; + uinteger_t size(const Loc& loc) override; + uint32_t alignsize() override; + TypeStruct* syntaxCopy() override; + Dsymbol* toDsymbol(Scope* sc) override; + structalign_t alignment() override; + Expression* defaultInitLiteral(const Loc& loc) override; + bool isZeroInit(const Loc& loc) override; + bool isAssignable() override; + bool isBoolean() override; + bool needsDestruction() override; + bool needsCopyOrPostblit() override; + bool needsNested() override; + bool hasPointers() override; + bool hasVoidInitPointers() override; + bool hasSystemFields() override; + bool hasInvariant() override; + MATCH implicitConvTo(Type* to) override; + MATCH constConv(Type* to) override; + uint8_t deduceWild(Type* t, bool isRef) override; + Type* toHeadMutable() override; void accept(Visitor* v) override; }; -class ThisDeclaration final : public VarDeclaration +class TypeTag final : public Type { public: - ThisDeclaration* syntaxCopy(Dsymbol* s) override; - ThisDeclaration* isThisDeclaration() override; + Loc loc; + TOK tok; + structalign_t packalign; + Identifier* id; + Type* base; + Array* members; + Type* resolved; + uint8_t mod; + const char* kind() const override; + TypeTag* syntaxCopy() override; void accept(Visitor* v) override; }; -class EnumDeclaration final : public ScopeDsymbol +class TypeTraits final : public Type { public: - Type* type; - Type* memtype; - Visibility visibility; - Expression* maxval; - Expression* minval; - Expression* defaultval; - bool isdeprecated() const; - bool isdeprecated(bool v); - bool added() const; - bool added(bool v); - bool inuse() const; - bool inuse(bool v); -private: - uint8_t bitFields; -public: - EnumDeclaration* syntaxCopy(Dsymbol* s) override; - bool oneMember(Dsymbol** ps, Identifier* ident) override; - Type* getType() override; - const char* kind() const override; - bool isDeprecated() const override; - Visibility visible() override; - bool isSpecial() const; - Expression* getDefaultValue(const Loc& loc); - Type* getMemtype(const Loc& loc); - EnumDeclaration* isEnumDeclaration() override; - Symbol* sinit; + Loc loc; + TraitsExp* exp; + RootObject* obj; + const char* kind() const override; + TypeTraits* syntaxCopy() override; + Dsymbol* toDsymbol(Scope* sc) override; void accept(Visitor* v) override; + uinteger_t size(const Loc& loc) override; }; -class EnumMember final : public VarDeclaration +class TypeTuple final : public Type { public: - Expression*& value(); - Expression* origValue; - Type* origType; - EnumDeclaration* ed; - EnumMember* syntaxCopy(Dsymbol* s) override; + static TypeTuple* empty; + Array* arguments; + static TypeTuple* create(Array* arguments); + static TypeTuple* create(); + static TypeTuple* create(Type* t1); + static TypeTuple* create(Type* t1, Type* t2); const char* kind() const override; - EnumMember* isEnumMember() override; + TypeTuple* syntaxCopy() override; + bool equals(const RootObject* const o) const override; + MATCH implicitConvTo(Type* to) override; void accept(Visitor* v) override; }; -class Import final : public Dsymbol +class TypeTypeof final : public TypeQualified { public: - _d_dynamicArray< Identifier* > packages; - Identifier* id; - Identifier* aliasId; - int32_t isstatic; - Visibility visibility; - Array names; - Array aliases; - Module* mod; - Package* pkg; - Array aliasdecls; + Expression* exp; + int32_t inuse; const char* kind() const override; - Visibility visible() override; - Import* syntaxCopy(Dsymbol* s) override; - void importAll(Scope* sc) override; - Dsymbol* toAlias() override; - bool overloadInsert(Dsymbol* s) override; - Import* isImport() override; + TypeTypeof* syntaxCopy() override; + Dsymbol* toDsymbol(Scope* sc) override; + uinteger_t size(const Loc& loc) override; void accept(Visitor* v) override; }; -extern Expression* ctfeInterpret(Expression* e); - -extern void printCtfePerformanceStats(); - -extern const char* mangleExact(FuncDeclaration* fd); - -extern void mangleToBuffer(Type* t, OutBuffer& buf); - -extern void mangleToBuffer(Expression* e, OutBuffer& buf); - -extern void mangleToBuffer(Dsymbol* s, OutBuffer& buf); +class TypeVector final : public Type +{ +public: + Type* basetype; + static TypeVector* create(Type* basetype); + const char* kind() const override; + TypeVector* syntaxCopy() override; + uinteger_t size(const Loc& loc) override; + uint32_t alignsize() override; + bool isintegral() override; + bool isfloating() override; + bool isscalar() override; + bool isunsigned() override; + bool isBoolean() override; + MATCH implicitConvTo(Type* to) override; + Expression* defaultInitLiteral(const Loc& loc) override; + TypeBasic* elementType(); + bool isZeroInit(const Loc& loc) override; + void accept(Visitor* v) override; +}; -extern void mangleToBuffer(TemplateInstance* ti, OutBuffer& buf); +extern AggregateDeclaration* isAggregate(Type* t); -class Package : public ScopeDsymbol +class Nspace final : public ScopeDsymbol { public: - PKG isPkgMod; - uint32_t tag; - Module* mod; + Expression* identExp; + Nspace* syntaxCopy(Dsymbol* s) override; + bool hasPointers() override; + void setFieldOffset(AggregateDeclaration* ad, FieldState& fieldState, bool isunion) override; const char* kind() const override; - bool equals(const RootObject* const o) const override; - Package* isPackage() final override; - bool isAncestorPackageOf(const Package* const pkg) const; + Nspace* isNspace() override; void accept(Visitor* v) override; - Module* isPackageMod(); - void resolvePKGunknown(); }; -class Module final : public Package +enum class STMT : uint8_t +{ + Error = 0u, + Peel = 1u, + Exp = 2u, + DtorExp = 3u, + Mixin = 4u, + Compound = 5u, + CompoundDeclaration = 6u, + CompoundAsm = 7u, + UnrolledLoop = 8u, + Scope = 9u, + Forwarding = 10u, + While = 11u, + Do = 12u, + For = 13u, + Foreach = 14u, + ForeachRange = 15u, + If = 16u, + Conditional = 17u, + StaticForeach = 18u, + Pragma = 19u, + StaticAssert = 20u, + Switch = 21u, + Case = 22u, + CaseRange = 23u, + Default = 24u, + GotoDefault = 25u, + GotoCase = 26u, + SwitchError = 27u, + Return = 28u, + Break = 29u, + Continue = 30u, + Synchronized = 31u, + With = 32u, + TryCatch = 33u, + TryFinally = 34u, + ScopeGuard = 35u, + Throw = 36u, + Debug = 37u, + Goto = 38u, + Label = 39u, + Asm = 40u, + InlineAsm = 41u, + GccAsm = 42u, + Import = 43u, +}; + +class Statement : public ASTNode { public: - static Module* rootModule; - static DsymbolTable* modules; - static Array amodules; - static Array deferred; - static Array deferred2; - static Array deferred3; - static void _init(); - static void deinitialize(); - static AggregateDeclaration* moduleinfo; - _d_dynamicArray< const char > arg; - ModuleDeclaration* md; - const FileName srcfile; - const FileName objfile; - const FileName hdrfile; - FileName docfile; - _d_dynamicArray< const uint8_t > src; - uint32_t errors; - uint32_t numlines; - FileType filetype; - bool hasAlwaysInlines; - bool isPackageFile; - Package* pkg; - Array contentImportedFiles; - int32_t needmoduleinfo; -private: - ThreeState selfimports; - ThreeState rootimports; -public: - void* tagSymTab; -private: - OutBuffer defines; -public: - bool selfImports(); - bool rootImports(); - Identifier* searchCacheIdent; - Dsymbol* searchCacheSymbol; - uint32_t searchCacheFlags; - bool insearch; - Module* importedFrom; - Array* decldefs; - Array aimports; - uint32_t debuglevel; - Array* debugids; - Array* debugidsNot; - uint32_t versionlevel; - Array* versionids; - Array* versionidsNot; - MacroTable macrotable; - Escape* _escapetable; - size_t nameoffset; - size_t namelen; - static Module* create(const char* filename, Identifier* ident, int32_t doDocComment, int32_t doHdrGen); - static const char* find(const char* filename); - static Module* load(const Loc& loc, Array* packages, Identifier* ident); - const char* kind() const override; - bool read(const Loc& loc); - Module* parse(); - void importAll(Scope* prevsc) override; - int32_t needModuleInfo(); - void checkImportDeprecation(const Loc& loc, Scope* sc); - bool isPackageAccessible(Package* p, Visibility visibility, uint32_t flags = 0u) override; - Dsymbol* symtabInsert(Dsymbol* s) override; - static void runDeferredSemantic(); - static void runDeferredSemantic2(); - static void runDeferredSemantic3(); - int32_t imports(Module* m); - bool isRoot(); - bool isCoreModule(Identifier* ident); - int32_t doppelganger; - Symbol* cov; - _d_dynamicArray< uint32_t > covb; - Symbol* sictor; - Symbol* sctor; - Symbol* sdtor; - Symbol* ssharedctor; - Symbol* sshareddtor; - Symbol* stest; - Symbol* sfilename; - void* ctfe_cov; - Module* isModule() override; + const Loc loc; + const STMT stmt; + DYNCAST dyncast() const final override; + virtual Statement* syntaxCopy(); + static Array* arraySyntaxCopy(Array* a); + virtual Statement* getRelatedLabeled(); + virtual bool hasBreak() const; + virtual bool hasContinue() const; + virtual Statement* last(); void accept(Visitor* v) override; - void fullyQualifiedName(OutBuffer& buf); + virtual ReturnStatement* endsWithReturnStatement(); + ErrorStatement* isErrorStatement(); + PeelStatement* isPeelStatement(); + ScopeStatement* isScopeStatement(); + ExpStatement* isExpStatement(); + CompoundStatement* isCompoundStatement(); + ReturnStatement* isReturnStatement(); + IfStatement* isIfStatement(); + ConditionalStatement* isConditionalStatement(); + StaticForeachStatement* isStaticForeachStatement(); + CaseStatement* isCaseStatement(); + DefaultStatement* isDefaultStatement(); + LabelStatement* isLabelStatement(); + GotoStatement* isGotoStatement(); + GotoDefaultStatement* isGotoDefaultStatement(); + GotoCaseStatement* isGotoCaseStatement(); + BreakStatement* isBreakStatement(); + DtorExpStatement* isDtorExpStatement(); + MixinStatement* isMixinStatement(); + ForwardingStatement* isForwardingStatement(); + DoStatement* isDoStatement(); + WhileStatement* isWhileStatement(); + ForStatement* isForStatement(); + ForeachStatement* isForeachStatement(); + SwitchStatement* isSwitchStatement(); + ContinueStatement* isContinueStatement(); + WithStatement* isWithStatement(); + TryCatchStatement* isTryCatchStatement(); + ThrowStatement* isThrowStatement(); + DebugStatement* isDebugStatement(); + TryFinallyStatement* isTryFinallyStatement(); + ScopeGuardStatement* isScopeGuardStatement(); + SwitchErrorStatement* isSwitchErrorStatement(); + UnrolledLoopStatement* isUnrolledLoopStatement(); + ForeachRangeStatement* isForeachRangeStatement(); + CompoundDeclarationStatement* isCompoundDeclarationStatement(); + CompoundAsmStatement* isCompoundAsmStatement(); + PragmaStatement* isPragmaStatement(); + StaticAssertStatement* isStaticAssertStatement(); + CaseRangeStatement* isCaseRangeStatement(); + SynchronizedStatement* isSynchronizedStatement(); + AsmStatement* isAsmStatement(); + InlineAsmStatement* isInlineAsmStatement(); + GccAsmStatement* isGccAsmStatement(); + ImportStatement* isImportStatement(); }; -struct ModuleDeclaration final +class AsmStatement : public Statement { - Loc loc; - Identifier* id; - _d_dynamicArray< Identifier* > packages; - bool isdeprecated; - Expression* msg; - const char* toChars() const; - ModuleDeclaration() : - loc(), - id(), - packages(), - isdeprecated(), - msg() - { - } +public: + Token* tokens; + bool caseSensitive; + AsmStatement* syntaxCopy() override; + void accept(Visitor* v) override; }; -extern void getLocalClasses(Module* mod, Array& aclasses); - -extern FuncDeclaration* findGetMembers(ScopeDsymbol* dsym); - -extern void gendocfile(Module* m, const char* const ddoctext_ptr, size_t ddoctext_length, const char* const datetime, ErrorSink* eSink, OutBuffer& outbuf); - -struct Scope final +class BreakStatement final : public Statement { - Scope* enclosing; - Module* _module; - ScopeDsymbol* scopesym; - FuncDeclaration* func; - VarDeclaration* varDecl; - Dsymbol* parent; - LabelStatement* slabel; - SwitchStatement* sw; - Statement* tryBody; - TryFinallyStatement* tf; - ScopeGuardStatement* os; - Statement* sbreak; - Statement* scontinue; - ForeachStatement* fes; - Scope* callsc; - Dsymbol* inunion; - bool nofree; - bool inLoop; - int32_t intypeof; - VarDeclaration* lastVar; - ErrorSink* eSink; - Module* minst; - TemplateInstance* tinst; - CtorFlow ctorflow; - AlignDeclaration* aligndecl; - CPPNamespaceDeclaration* namespace_; - LINK linkage; - CPPMANGLE cppmangle; - PragmaDeclaration* inlining; - Visibility visibility; - int32_t explicitVisibility; - StorageClass stc; - DeprecatedDeclaration* depdecl; - uint32_t flags; - UserAttributeDeclaration* userAttribDecl; - DocComment* lastdc; - void* anchorCounts; - Identifier* prevAnchor; - AliasDeclaration* aliasAsg; - Dsymbol* search(const Loc& loc, Identifier* ident, Dsymbol*& pscopesym, uint32_t flags = 0u); - Scope() : - enclosing(), - _module(), - scopesym(), - func(), - varDecl(), - parent(), - slabel(), - sw(), - tryBody(), - tf(), - os(), - sbreak(), - scontinue(), - fes(), - callsc(), - inunion(), - nofree(), - inLoop(), - intypeof(), - lastVar(), - eSink(), - minst(), - tinst(), - ctorflow(), - aligndecl(), - namespace_(), - linkage((LINK)1u), - cppmangle((CPPMANGLE)0u), - inlining(), - visibility(Visibility((Visibility::Kind)5u, nullptr)), - explicitVisibility(), - stc(), - depdecl(), - flags(), - userAttribDecl(), - lastdc(), - prevAnchor(), - aliasAsg() - { - } - Scope(Scope* enclosing, Module* _module = nullptr, ScopeDsymbol* scopesym = nullptr, FuncDeclaration* func = nullptr, VarDeclaration* varDecl = nullptr, Dsymbol* parent = nullptr, LabelStatement* slabel = nullptr, SwitchStatement* sw = nullptr, Statement* tryBody = nullptr, TryFinallyStatement* tf = nullptr, ScopeGuardStatement* os = nullptr, Statement* sbreak = nullptr, Statement* scontinue = nullptr, ForeachStatement* fes = nullptr, Scope* callsc = nullptr, Dsymbol* inunion = nullptr, bool nofree = false, bool inLoop = false, int32_t intypeof = 0, VarDeclaration* lastVar = nullptr, ErrorSink* eSink = nullptr, Module* minst = nullptr, TemplateInstance* tinst = nullptr, CtorFlow ctorflow = CtorFlow(), AlignDeclaration* aligndecl = nullptr, CPPNamespaceDeclaration* namespace_ = nullptr, LINK linkage = (LINK)1u, CPPMANGLE cppmangle = (CPPMANGLE)0u, PragmaDeclaration* inlining = nullptr, Visibility visibility = Visibility((Visibility::Kind)5u, nullptr), int32_t explicitVisibility = 0, uint64_t stc = 0LLU, DeprecatedDeclaration* depdecl = nullptr, uint32_t flags = 0u, UserAttributeDeclaration* userAttribDecl = nullptr, DocComment* lastdc = nullptr, void* anchorCounts = nullptr, Identifier* prevAnchor = nullptr, AliasDeclaration* aliasAsg = nullptr) : - enclosing(enclosing), - _module(_module), - scopesym(scopesym), - func(func), - varDecl(varDecl), - parent(parent), - slabel(slabel), - sw(sw), - tryBody(tryBody), - tf(tf), - os(os), - sbreak(sbreak), - scontinue(scontinue), - fes(fes), - callsc(callsc), - inunion(inunion), - nofree(nofree), - inLoop(inLoop), - intypeof(intypeof), - lastVar(lastVar), - eSink(eSink), - minst(minst), - tinst(tinst), - ctorflow(ctorflow), - aligndecl(aligndecl), - namespace_(namespace_), - linkage(linkage), - cppmangle(cppmangle), - inlining(inlining), - visibility(visibility), - explicitVisibility(explicitVisibility), - stc(stc), - depdecl(depdecl), - flags(flags), - userAttribDecl(userAttribDecl), - lastdc(lastdc), - anchorCounts(anchorCounts), - prevAnchor(prevAnchor), - aliasAsg(aliasAsg) - {} +public: + Identifier* ident; + BreakStatement* syntaxCopy() override; + void accept(Visitor* v) override; }; -extern FuncDeclaration* search_toString(StructDeclaration* sd); - -class StructDeclaration : public AggregateDeclaration +class CaseRangeStatement final : public Statement { public: - Array postblits; - FuncDeclaration* postblit; - FuncDeclaration* xeq; - FuncDeclaration* xcmp; - FuncDeclaration* xhash; - static FuncDeclaration* xerreq; - static FuncDeclaration* xerrcmp; - TypeTuple* argTypes; - structalign_t alignment; - ThreeState ispod; - bool zeroInit() const; - bool zeroInit(bool v); - bool hasIdentityAssign() const; - bool hasIdentityAssign(bool v); - bool hasBlitAssign() const; - bool hasBlitAssign(bool v); - bool hasIdentityEquals() const; - bool hasIdentityEquals(bool v); - bool hasNoFields() const; - bool hasNoFields(bool v); - bool hasCopyCtor() const; - bool hasCopyCtor(bool v); - bool hasPointerField() const; - bool hasPointerField(bool v); - bool hasVoidInitPointers() const; - bool hasVoidInitPointers(bool v); - bool hasSystemFields() const; - bool hasSystemFields(bool v); - bool hasFieldWithInvariant() const; - bool hasFieldWithInvariant(bool v); - bool computedTypeProperties() const; - bool computedTypeProperties(bool v); - bool requestTypeInfo() const; - bool requestTypeInfo(bool v); -private: - uint16_t bitFields; + Expression* first; + Expression* last; + Statement* statement; + CaseRangeStatement* syntaxCopy() override; + void accept(Visitor* v) override; +}; + +class CaseStatement final : public Statement +{ public: - static StructDeclaration* create(const Loc& loc, Identifier* id, bool inObject); - StructDeclaration* syntaxCopy(Dsymbol* s) override; - const char* kind() const override; - void finalizeSize() final override; - bool isPOD(); - bool hasCopyConstruction(); - StructDeclaration* isStructDeclaration() final override; + Expression* exp; + Statement* statement; + int32_t index; + VarDeclaration* lastVar; + void* extra; + CaseStatement* syntaxCopy() override; void accept(Visitor* v) override; - uint32_t numArgTypes() const; - Type* argType(uint32_t index); - bool hasRegularCtor(bool checkDisabled = false); }; -class UnionDeclaration final : public StructDeclaration +class Catch final : public RootObject { public: - UnionDeclaration* syntaxCopy(Dsymbol* s) override; - const char* kind() const override; - UnionDeclaration* isUnionDeclaration() override; + const Loc loc; + Type* type; + Identifier* ident; + Statement* handler; + VarDeclaration* var; + bool errors; + bool internalCatch; + Catch* syntaxCopy(); +}; + +class CompoundStatement : public Statement +{ +public: + Array* statements; + static CompoundStatement* create(const Loc& loc, Statement* s1, Statement* s2); + CompoundStatement* syntaxCopy() override; + ReturnStatement* endsWithReturnStatement() final override; + Statement* last() final override; void accept(Visitor* v) override; }; -class WithScopeSymbol final : public ScopeDsymbol +class CompoundAsmStatement final : public CompoundStatement { public: - WithStatement* withstate; - WithScopeSymbol* isWithScopeSymbol() override; + StorageClass stc; + CompoundAsmStatement* syntaxCopy() override; void accept(Visitor* v) override; }; -class ArrayScopeSymbol final : public ScopeDsymbol +class CompoundDeclarationStatement final : public CompoundStatement { public: - RootObject* arrayContent; - ArrayScopeSymbol* isArrayScopeSymbol() override; + CompoundDeclarationStatement* syntaxCopy() override; void accept(Visitor* v) override; }; -class OverloadSet final : public Dsymbol +class ConditionalStatement final : public Statement { public: - Array a; - void push(Dsymbol* s); - OverloadSet* isOverloadSet() override; - const char* kind() const override; + Condition* condition; + Statement* ifbody; + Statement* elsebody; + ConditionalStatement* syntaxCopy() override; void accept(Visitor* v) override; }; -class ForwardingScopeDsymbol final : public ScopeDsymbol +class ContinueStatement final : public Statement { public: - Dsymbol* symtabInsert(Dsymbol* s) override; - Dsymbol* symtabLookup(Dsymbol* s, Identifier* id) override; - void importScope(Dsymbol* s, Visibility visibility) override; - const char* kind() const override; - ForwardingScopeDsymbol* isForwardingScopeDsymbol() override; + Identifier* ident; + ContinueStatement* syntaxCopy() override; + void accept(Visitor* v) override; }; -class ExpressionDsymbol final : public Dsymbol +class DebugStatement final : public Statement { public: - Expression* exp; - ExpressionDsymbol(Expression* exp); - ExpressionDsymbol* isExpressionDsymbol() override; + Statement* statement; + DebugStatement* syntaxCopy() override; + void accept(Visitor* v) override; }; -class AliasAssign final : public Dsymbol +class DefaultStatement final : public Statement { public: - Identifier* ident; - Type* type; - Dsymbol* aliassym; - AliasAssign* syntaxCopy(Dsymbol* s) override; - AliasAssign* isAliasAssign() override; - const char* kind() const override; + Statement* statement; + VarDeclaration* lastVar; + DefaultStatement* syntaxCopy() override; void accept(Visitor* v) override; }; -class DsymbolTable final : public RootObject +class DoStatement final : public Statement { public: - AssocArray tab; - Dsymbol* lookup(const Identifier* const ident); - void update(Dsymbol* s); - Dsymbol* insert(Dsymbol* s); - Dsymbol* insert(const Identifier* const ident, Dsymbol* s); - size_t length() const; - DsymbolTable(); + Statement* _body; + Expression* condition; + Loc endloc; + DoStatement* syntaxCopy() override; + bool hasBreak() const override; + bool hasContinue() const override; + void accept(Visitor* v) override; }; -extern void dsymbolSemantic(Dsymbol* dsym, Scope* sc); - -extern void addMember(Dsymbol* dsym, Scope* sc, ScopeDsymbol* sds); - -extern Dsymbol* search(Dsymbol* d, const Loc& loc, Identifier* ident, uint32_t flags = 0u); - -extern void setScope(Dsymbol* d, Scope* sc); - -extern Expression* isExpression(RootObject* o); - -extern Dsymbol* isDsymbol(RootObject* o); - -extern Type* isType(RootObject* o); - -extern Tuple* isTuple(RootObject* o); - -extern Parameter* isParameter(RootObject* o); - -extern TemplateParameter* isTemplateParameter(RootObject* o); - -extern bool isError(const RootObject* const o); - -class Tuple final : public RootObject +class ExpStatement : public Statement { public: - Array objects; - DYNCAST dyncast() const override; - const char* toChars() const override; + Expression* exp; + static ExpStatement* create(const Loc& loc, Expression* exp); + ExpStatement* syntaxCopy() override; + void accept(Visitor* v) override; }; -class TemplateDeclaration final : public ScopeDsymbol +class DtorExpStatement final : public ExpStatement { public: - Array* parameters; - Array* origParameters; - Expression* constraint; - void* instances; - TemplateDeclaration* overnext; - TemplateDeclaration* overroot; - FuncDeclaration* funcroot; - Dsymbol* onemember; - bool literal; - bool ismixin; - bool isstatic; - bool isTrivialAliasSeq; - bool isTrivialAlias; - bool deprecated_; - Visibility visibility; - TemplatePrevious* previous; -private: - Expression* lastConstraint; - Array lastConstraintNegs; - Array* lastConstraintTiargs; -public: - TemplateDeclaration* syntaxCopy(Dsymbol* __param_0_) override; - bool overloadInsert(Dsymbol* s) override; - bool hasStaticCtorOrDtor() override; - const char* kind() const override; - const char* toChars() const override; - const char* toCharsNoConstraints() const; - const char* toCharsMaybeConstraints(bool includeConstraints) const; - Visibility visible() override; - const char* getConstraintEvalError(const char*& tip); - Scope* scopeForTemplateParameters(TemplateInstance* ti, Scope* sc); - TemplateDeclaration* isTemplateDeclaration() override; - bool isDeprecated() const override; - bool isOverloadable() const override; + VarDeclaration* var; + DtorExpStatement* syntaxCopy() override; void accept(Visitor* v) override; }; -class TypeDeduced final : public Type +class ErrorStatement final : public Statement { public: - Type* tded; - Array argexps; - Array tparams; - void update(Expression* e, Type* tparam); - void update(Type* tt, Expression* e, Type* tparam); - MATCH matchAll(Type* tt); + ErrorStatement* syntaxCopy() override; + void accept(Visitor* v) override; }; -class TemplateParameter : public ASTNode +class ForStatement final : public Statement { public: - Loc loc; - Identifier* ident; - bool dependent; - virtual TemplateTypeParameter* isTemplateTypeParameter(); - virtual TemplateValueParameter* isTemplateValueParameter(); - virtual TemplateAliasParameter* isTemplateAliasParameter(); - virtual TemplateThisParameter* isTemplateThisParameter(); - virtual TemplateTupleParameter* isTemplateTupleParameter(); - virtual TemplateParameter* syntaxCopy() = 0; - virtual bool declareParameter(Scope* sc) = 0; - virtual void print(RootObject* oarg, RootObject* oded) = 0; - virtual RootObject* specialization() = 0; - virtual RootObject* defaultArg(const Loc& instLoc, Scope* sc) = 0; - virtual bool hasDefaultArg() = 0; - const char* toChars() const override; - DYNCAST dyncast() const override; - virtual RootObject* dummyArg() = 0; + Statement* _init; + Expression* condition; + Expression* increment; + Statement* _body; + Loc endloc; + Statement* relatedLabeled; + ForStatement* syntaxCopy() override; + Statement* getRelatedLabeled() override; + bool hasBreak() const override; + bool hasContinue() const override; void accept(Visitor* v) override; }; -class TemplateTypeParameter : public TemplateParameter +class ForeachRangeStatement final : public Statement { public: - Type* specType; - Type* defaultType; - TemplateTypeParameter* isTemplateTypeParameter() final override; - TemplateTypeParameter* syntaxCopy() override; - bool declareParameter(Scope* sc) final override; - void print(RootObject* oarg, RootObject* oded) final override; - RootObject* specialization() final override; - RootObject* defaultArg(const Loc& instLoc, Scope* sc) final override; - bool hasDefaultArg() final override; - RootObject* dummyArg() final override; + TOK op; + Parameter* prm; + Expression* lwr; + Expression* upr; + Statement* _body; + Loc endloc; + VarDeclaration* key; + ForeachRangeStatement* syntaxCopy() override; + bool hasBreak() const override; + bool hasContinue() const override; void accept(Visitor* v) override; }; -class TemplateThisParameter final : public TemplateTypeParameter +class ForeachStatement final : public Statement { public: - TemplateThisParameter* isTemplateThisParameter() override; - TemplateThisParameter* syntaxCopy() override; + TOK op; + Array* parameters; + Expression* aggr; + Statement* _body; + Loc endloc; + VarDeclaration* key; + VarDeclaration* value; + FuncDeclaration* func; + Array* cases; + Array* gotos; + ForeachStatement* syntaxCopy() override; + bool hasBreak() const override; + bool hasContinue() const override; void accept(Visitor* v) override; }; -class TemplateValueParameter final : public TemplateParameter +class ForwardingStatement final : public Statement { public: - Type* valType; - Expression* specValue; - Expression* defaultValue; - TemplateValueParameter* isTemplateValueParameter() override; - TemplateValueParameter* syntaxCopy() override; - bool declareParameter(Scope* sc) override; - void print(RootObject* oarg, RootObject* oded) override; - RootObject* specialization() override; - RootObject* defaultArg(const Loc& instLoc, Scope* sc) override; - bool hasDefaultArg() override; - RootObject* dummyArg() override; + ForwardingScopeDsymbol* sym; + Statement* statement; + ForwardingStatement* syntaxCopy() override; void accept(Visitor* v) override; }; -class TemplateAliasParameter final : public TemplateParameter +class GccAsmStatement final : public AsmStatement { public: - Type* specType; - RootObject* specAlias; - RootObject* defaultAlias; - TemplateAliasParameter* isTemplateAliasParameter() override; - TemplateAliasParameter* syntaxCopy() override; - bool declareParameter(Scope* sc) override; - void print(RootObject* oarg, RootObject* oded) override; - RootObject* specialization() override; - RootObject* defaultArg(const Loc& instLoc, Scope* sc) override; - bool hasDefaultArg() override; - RootObject* dummyArg() override; + StorageClass stc; + Expression* insn; + Array* args; + uint32_t outputargs; + Array* names; + Array* constraints; + Array* clobbers; + Array* labels; + Array* gotos; + GccAsmStatement* syntaxCopy() override; void accept(Visitor* v) override; }; -class TemplateTupleParameter final : public TemplateParameter +class GotoCaseStatement final : public Statement { public: - TemplateTupleParameter* isTemplateTupleParameter() override; - TemplateTupleParameter* syntaxCopy() override; - bool declareParameter(Scope* sc) override; - void print(RootObject* oarg, RootObject* oded) override; - RootObject* specialization() override; - RootObject* defaultArg(const Loc& instLoc, Scope* sc) override; - bool hasDefaultArg() override; - RootObject* dummyArg() override; + Expression* exp; + CaseStatement* cs; + GotoCaseStatement* syntaxCopy() override; void accept(Visitor* v) override; }; -class TemplateInstance : public ScopeDsymbol +class GotoDefaultStatement final : public Statement { public: - Identifier* name; - Array* tiargs; - Array tdtypes; - Array importedModules; - Dsymbol* tempdecl; - Dsymbol* enclosing; - Dsymbol* aliasdecl; - TemplateInstance* inst; - ScopeDsymbol* argsym; - size_t hash; - Array* fargs; - Array* deferred; - Module* memberOf; - TemplateInstance* tinst; - TemplateInstance* tnext; - Module* minst; -private: - uint16_t _nest; -public: - uint8_t inuse; -private: - enum class Flag : uint32_t - { - semantictiargsdone = 32768u, - havetempdecl = 16384u, - gagged = 8192u, - available = 8191u, - }; - -public: - TemplateInstance* syntaxCopy(Dsymbol* s) override; - Dsymbol* toAlias() final override; - const char* kind() const override; - bool oneMember(Dsymbol** ps, Identifier* ident) override; - const char* toChars() const override; - const char* toPrettyCharsHelper() final override; - Identifier* getIdent() final override; - bool equalsx(TemplateInstance* ti); - bool isDiscardable(); - bool needsCodegen(); - TemplateInstance* isTemplateInstance() final override; + SwitchStatement* sw; + GotoDefaultStatement* syntaxCopy() override; void accept(Visitor* v) override; }; -class TemplateMixin final : public TemplateInstance +class GotoStatement final : public Statement { public: - TypeQualified* tqual; - TemplateInstance* syntaxCopy(Dsymbol* s) override; - const char* kind() const override; - bool oneMember(Dsymbol** ps, Identifier* ident) override; - bool hasPointers() override; - void setFieldOffset(AggregateDeclaration* ad, FieldState& fieldState, bool isunion) override; - const char* toChars() const override; - TemplateMixin* isTemplateMixin() override; + Identifier* ident; + LabelDsymbol* label; + Statement* tryBody; + TryFinallyStatement* tf; + ScopeGuardStatement* os; + VarDeclaration* lastVar; + bool inCtfeBlock; + GotoStatement* syntaxCopy() override; void accept(Visitor* v) override; }; -extern void printTemplateStats(); - -extern void genCppHdrFiles(Array& ms); - -class DebugSymbol final : public Dsymbol +class IfStatement final : public Statement { public: - uint32_t level; - DebugSymbol* syntaxCopy(Dsymbol* s) override; - const char* toChars() const override; - const char* kind() const override; - DebugSymbol* isDebugSymbol() override; + Parameter* prm; + Expression* condition; + Statement* ifbody; + Statement* elsebody; + VarDeclaration* match; + Loc endloc; + IfStatement* syntaxCopy() override; void accept(Visitor* v) override; + bool isIfCtfeBlock(); }; -class VersionSymbol final : public Dsymbol +class ImportStatement final : public Statement { public: - uint32_t level; - VersionSymbol* syntaxCopy(Dsymbol* s) override; - const char* toChars() const override; - const char* kind() const override; - VersionSymbol* isVersionSymbol() override; + Array* imports; + ImportStatement* syntaxCopy() override; void accept(Visitor* v) override; }; -extern void expandTuples(Array* exps, Array* names = nullptr); - -class Expression : public ASTNode +class InlineAsmStatement final : public AsmStatement { public: - Type* type; - Loc loc; - const EXP op; - size_t size() const; - static void _init(); - static void deinitialize(); - virtual Expression* syntaxCopy(); - DYNCAST dyncast() const final override; - const char* toChars() const override; - virtual dinteger_t toInteger(); - virtual uinteger_t toUInteger(); - virtual _d_real toReal(); - virtual _d_real toImaginary(); - virtual complex_t toComplex(); - virtual StringExp* toStringExp(); - virtual bool isLvalue(); - virtual bool checkType(); - virtual bool checkValue(); - Expression* addressOf(); - Expression* deref(); - int32_t isConst(); - virtual bool isIdentical(const Expression* const e) const; - virtual Optional toBool(); - virtual bool hasCode(); - IntegerExp* isIntegerExp(); - ErrorExp* isErrorExp(); - VoidInitExp* isVoidInitExp(); - RealExp* isRealExp(); - ComplexExp* isComplexExp(); - IdentifierExp* isIdentifierExp(); - DollarExp* isDollarExp(); - DsymbolExp* isDsymbolExp(); - ThisExp* isThisExp(); - SuperExp* isSuperExp(); - NullExp* isNullExp(); - StringExp* isStringExp(); - TupleExp* isTupleExp(); - ArrayLiteralExp* isArrayLiteralExp(); - AssocArrayLiteralExp* isAssocArrayLiteralExp(); - StructLiteralExp* isStructLiteralExp(); - CompoundLiteralExp* isCompoundLiteralExp(); - TypeExp* isTypeExp(); - ScopeExp* isScopeExp(); - TemplateExp* isTemplateExp(); - NewExp* isNewExp(); - NewAnonClassExp* isNewAnonClassExp(); - SymOffExp* isSymOffExp(); - VarExp* isVarExp(); - OverExp* isOverExp(); - FuncExp* isFuncExp(); - DeclarationExp* isDeclarationExp(); - TypeidExp* isTypeidExp(); - TraitsExp* isTraitsExp(); - HaltExp* isHaltExp(); - IsExp* isExp(); - MixinExp* isMixinExp(); - ImportExp* isImportExp(); - AssertExp* isAssertExp(); - ThrowExp* isThrowExp(); - DotIdExp* isDotIdExp(); - DotTemplateExp* isDotTemplateExp(); - DotVarExp* isDotVarExp(); - DotTemplateInstanceExp* isDotTemplateInstanceExp(); - DelegateExp* isDelegateExp(); - DotTypeExp* isDotTypeExp(); - CallExp* isCallExp(); - AddrExp* isAddrExp(); - PtrExp* isPtrExp(); - NegExp* isNegExp(); - UAddExp* isUAddExp(); - ComExp* isComExp(); - NotExp* isNotExp(); - DeleteExp* isDeleteExp(); - CastExp* isCastExp(); - VectorExp* isVectorExp(); - VectorArrayExp* isVectorArrayExp(); - SliceExp* isSliceExp(); - ArrayLengthExp* isArrayLengthExp(); - ArrayExp* isArrayExp(); - DotExp* isDotExp(); - CommaExp* isCommaExp(); - IntervalExp* isIntervalExp(); - DelegatePtrExp* isDelegatePtrExp(); - DelegateFuncptrExp* isDelegateFuncptrExp(); - IndexExp* isIndexExp(); - PostExp* isPostExp(); - PreExp* isPreExp(); - AssignExp* isAssignExp(); - LoweredAssignExp* isLoweredAssignExp(); - ConstructExp* isConstructExp(); - BlitExp* isBlitExp(); - AddAssignExp* isAddAssignExp(); - MinAssignExp* isMinAssignExp(); - MulAssignExp* isMulAssignExp(); - DivAssignExp* isDivAssignExp(); - ModAssignExp* isModAssignExp(); - AndAssignExp* isAndAssignExp(); - OrAssignExp* isOrAssignExp(); - XorAssignExp* isXorAssignExp(); - PowAssignExp* isPowAssignExp(); - ShlAssignExp* isShlAssignExp(); - ShrAssignExp* isShrAssignExp(); - UshrAssignExp* isUshrAssignExp(); - CatAssignExp* isCatAssignExp(); - CatElemAssignExp* isCatElemAssignExp(); - CatDcharAssignExp* isCatDcharAssignExp(); - AddExp* isAddExp(); - MinExp* isMinExp(); - CatExp* isCatExp(); - MulExp* isMulExp(); - DivExp* isDivExp(); - ModExp* isModExp(); - PowExp* isPowExp(); - ShlExp* isShlExp(); - ShrExp* isShrExp(); - UshrExp* isUshrExp(); - AndExp* isAndExp(); - OrExp* isOrExp(); - XorExp* isXorExp(); - LogicalExp* isLogicalExp(); - InExp* isInExp(); - RemoveExp* isRemoveExp(); - EqualExp* isEqualExp(); - IdentityExp* isIdentityExp(); - CondExp* isCondExp(); - GenericExp* isGenericExp(); - DefaultInitExp* isDefaultInitExp(); - FileInitExp* isFileInitExp(); - LineInitExp* isLineInitExp(); - ModuleInitExp* isModuleInitExp(); - FuncInitExp* isFuncInitExp(); - PrettyFuncInitExp* isPrettyFuncInitExp(); - ObjcClassReferenceExp* isObjcClassReferenceExp(); - ClassReferenceExp* isClassReferenceExp(); - ThrownExceptionExp* isThrownExceptionExp(); - UnaExp* isUnaExp(); - BinExp* isBinExp(); - BinAssignExp* isBinAssignExp(); + code* asmcode; + uint32_t asmalign; + uint32_t regs; + bool refparam; + bool naked; + InlineAsmStatement* syntaxCopy() override; + void accept(Visitor* v) override; +}; + +class LabelDsymbol final : public Dsymbol +{ +public: + LabelStatement* statement; + bool deleted; + bool iasm; + bool duplicated; + static LabelDsymbol* create(Identifier* ident); + LabelDsymbol* isLabel() override; void accept(Visitor* v) override; }; -class IntegerExp final : public Expression +class LabelStatement final : public Statement { - dinteger_t value; public: - static IntegerExp* create(const Loc& loc, dinteger_t value, Type* type); - bool equals(const RootObject* const o) const override; - dinteger_t toInteger() override; - _d_real toReal() override; - _d_real toImaginary() override; - complex_t toComplex() override; - Optional toBool() override; + Identifier* ident; + Statement* statement; + Statement* tryBody; + TryFinallyStatement* tf; + ScopeGuardStatement* os; + VarDeclaration* lastVar; + Statement* gotoTarget; + void* extra; + bool breaks; + bool inCtfeBlock; + LabelStatement* syntaxCopy() override; void accept(Visitor* v) override; - dinteger_t getInteger(); - IntegerExp* syntaxCopy() override; - static IntegerExp* createBool(bool b); }; -class ErrorExp final : public Expression +class MixinStatement final : public Statement { public: - static ErrorExp* get(); + Array* exps; + MixinStatement* syntaxCopy() override; void accept(Visitor* v) override; - static ErrorExp* errorexp; }; -class VoidInitExp final : public Expression +class PeelStatement final : public Statement { public: - VarDeclaration* var; + Statement* s; void accept(Visitor* v) override; }; -class RealExp final : public Expression +class PragmaStatement final : public Statement { public: - _d_real value; - static RealExp* create(const Loc& loc, _d_real value, Type* type); - bool equals(const RootObject* const o) const override; - bool isIdentical(const Expression* const e) const override; - dinteger_t toInteger() override; - uinteger_t toUInteger() override; - _d_real toReal() override; - _d_real toImaginary() override; - complex_t toComplex() override; - Optional toBool() override; + const Identifier* const ident; + Array* args; + Statement* _body; + PragmaStatement* syntaxCopy() override; void accept(Visitor* v) override; }; -class ComplexExp final : public Expression +class ReturnStatement final : public Statement { public: - complex_t value; - static ComplexExp* create(const Loc& loc, complex_t value, Type* type); - bool equals(const RootObject* const o) const override; - bool isIdentical(const Expression* const e) const override; - dinteger_t toInteger() override; - uinteger_t toUInteger() override; - _d_real toReal() override; - _d_real toImaginary() override; - complex_t toComplex() override; - Optional toBool() override; + Expression* exp; + size_t caseDim; + ReturnStatement* syntaxCopy() override; + ReturnStatement* endsWithReturnStatement() override; void accept(Visitor* v) override; }; -class IdentifierExp : public Expression +class ScopeGuardStatement final : public Statement { public: - Identifier* ident; - bool parens; - static IdentifierExp* create(const Loc& loc, Identifier* ident); - bool isLvalue() final override; + TOK tok; + Statement* statement; + ScopeGuardStatement* syntaxCopy() override; void accept(Visitor* v) override; }; -class DollarExp final : public IdentifierExp +class ScopeStatement final : public Statement { public: + Statement* statement; + Loc endloc; + ScopeStatement* syntaxCopy() override; + ReturnStatement* endsWithReturnStatement() override; + bool hasBreak() const override; + bool hasContinue() const override; void accept(Visitor* v) override; }; -class DsymbolExp final : public Expression +class StaticAssertStatement final : public Statement { public: - Dsymbol* s; - bool hasOverloads; - bool isLvalue() override; + StaticAssert* sa; + StaticAssertStatement* syntaxCopy() override; void accept(Visitor* v) override; }; -class ThisExp : public Expression +class StaticForeachStatement final : public Statement { public: - VarDeclaration* var; - ThisExp(const Loc& loc, const EXP tok); - ThisExp* syntaxCopy() override; - Optional toBool() override; - bool isLvalue() final override; + StaticForeach* sfe; + StaticForeachStatement* syntaxCopy() override; void accept(Visitor* v) override; }; -class SuperExp final : public ThisExp +class SwitchErrorStatement final : public Statement { public: + Expression* exp; void accept(Visitor* v) override; }; -class NullExp final : public Expression +class SwitchStatement final : public Statement { public: - bool equals(const RootObject* const o) const override; - Optional toBool() override; - StringExp* toStringExp() override; + Parameter* param; + Expression* condition; + Statement* _body; + bool isFinal; + Loc endloc; + bool hasDefault; + bool hasVars; + DefaultStatement* sdefault; + Statement* tryBody; + TryFinallyStatement* tf; + Array gotoCases; + Array* cases; + VarDeclaration* lastVar; + SwitchStatement* syntaxCopy() override; + bool hasBreak() const override; void accept(Visitor* v) override; }; -class StringExp final : public Expression +class SynchronizedStatement final : public Statement { public: - char postfix; - OwnedBy ownedByCtfe; - union + Expression* exp; + Statement* _body; + SynchronizedStatement* syntaxCopy() override; + bool hasBreak() const override; + bool hasContinue() const override; + void accept(Visitor* v) override; +}; + +class ThrowStatement final : public Statement +{ +public: + Expression* exp; + bool internalThrow; + ThrowStatement* syntaxCopy() override; + void accept(Visitor* v) override; +}; + +class TryCatchStatement final : public Statement +{ +public: + Statement* _body; + Array* catches; + Statement* tryBody; + TryCatchStatement* syntaxCopy() override; + bool hasBreak() const override; + void accept(Visitor* v) override; +}; + +class TryFinallyStatement final : public Statement +{ +public: + Statement* _body; + Statement* finalbody; + Statement* tryBody; + bool bodyFallsThru; + static TryFinallyStatement* create(const Loc& loc, Statement* _body, Statement* finalbody); + TryFinallyStatement* syntaxCopy() override; + bool hasBreak() const override; + bool hasContinue() const override; + void accept(Visitor* v) override; +}; + +class UnrolledLoopStatement final : public Statement +{ +public: + Array* statements; + UnrolledLoopStatement* syntaxCopy() override; + bool hasBreak() const override; + bool hasContinue() const override; + void accept(Visitor* v) override; +}; + +class WhileStatement final : public Statement +{ +public: + Parameter* param; + Expression* condition; + Statement* _body; + Loc endloc; + WhileStatement* syntaxCopy() override; + bool hasBreak() const override; + bool hasContinue() const override; + void accept(Visitor* v) override; +}; + +class WithStatement final : public Statement +{ +public: + Expression* exp; + Statement* _body; + VarDeclaration* wthis; + Loc endloc; + WithStatement* syntaxCopy() override; + void accept(Visitor* v) override; +}; + +class StaticAssert final : public Dsymbol +{ +public: + Expression* exp; + Array* msgs; + StaticAssert* syntaxCopy(Dsymbol* s) override; + bool oneMember(Dsymbol** ps, Identifier* ident) override; + const char* kind() const override; + StaticAssert* isStaticAssert() override; + void accept(Visitor* v) override; +}; + +extern Expression* defaultInit(Type* mt, const Loc& loc, const bool isCfile = false); + +extern Type* merge(Type* type); + +extern Type* typeSemantic(Type* type, const Loc& loc, Scope* sc); + +struct UnionExp final +{ + #pragma pack(push, 8) +private: + union _AnonStruct_u { - char* string; - char16_t* wstring; - char32_t* dstring; + char exp[29LLU]; + char integerexp[40LLU]; + char errorexp[29LLU]; + char realexp[48LLU]; + char complexexp[64LLU]; + char symoffexp[64LLU]; + char stringexp[51LLU]; + char arrayliteralexp[48LLU]; + char assocarrayliteralexp[56LLU]; + char structliteralexp[76LLU]; + char compoundliteralexp[40LLU]; + char nullexp[29LLU]; + char dotvarexp[49LLU]; + char addrexp[40LLU]; + char indexexp[74LLU]; + char sliceexp[65LLU]; + char vectorexp[53LLU]; }; - size_t len; - uint8_t sz; - bool committed; - bool hexString; - enum : char { NoPostfix = 0u }; - - static StringExp* create(const Loc& loc, const char* s); - static StringExp* create(const Loc& loc, const void* string, size_t len); - bool equals(const RootObject* const o) const override; - size_t numberOfCodeUnits(int32_t tynto = 0) const; - void writeTo(void* dest, bool zero, int32_t tyto = 0) const; - char32_t getCodeUnit(size_t i) const; - StringExp* toStringExp() override; - int32_t compare(const StringExp* const se2) const; - Optional toBool() override; - bool isLvalue() override; - void accept(Visitor* v) override; -}; + #pragma pack(pop) -class TupleExp final : public Expression -{ + // Ignoring var u alignment 8 + _AnonStruct_u u; public: - Expression* e0; - Array* exps; - static TupleExp* create(const Loc& loc, Array* exps); - TupleExp* syntaxCopy() override; - bool equals(const RootObject* const o) const override; - void accept(Visitor* v) override; + UnionExp() : + u() + { + } }; -class ArrayLiteralExp final : public Expression +enum class MODFlags { -public: - OwnedBy ownedByCtfe; - bool onstack; - Expression* basis; - Array* elements; - static ArrayLiteralExp* create(const Loc& loc, Array* elements); - ArrayLiteralExp* syntaxCopy() override; - bool equals(const RootObject* const o) const override; - Expression* getElement(size_t i); - Optional toBool() override; - StringExp* toStringExp() override; - void accept(Visitor* v) override; + none = 0, + const_ = 1, + immutable_ = 4, + shared_ = 2, + wild = 8, + wildconst = 9, + mutable_ = 16, }; -class AssocArrayLiteralExp final : public Expression +enum class STC : uint64_t { -public: - OwnedBy ownedByCtfe; - Array* keys; - Array* values; - Expression* lowering; - bool equals(const RootObject* const o) const override; - AssocArrayLiteralExp* syntaxCopy() override; - Optional toBool() override; - void accept(Visitor* v) override; + undefined_ = 0LLU, + static_ = 1LLU, + extern_ = 2LLU, + const_ = 4LLU, + final_ = 8LLU, + abstract_ = 16LLU, + parameter = 32LLU, + field = 64LLU, + override_ = 128LLU, + auto_ = 256LLU, + synchronized_ = 512LLU, + deprecated_ = 1024LLU, + in_ = 2048LLU, + out_ = 4096LLU, + lazy_ = 8192LLU, + foreach_ = 16384LLU, + variadic = 32768LLU, + templateparameter = 131072LLU, + ref_ = 262144LLU, + scope_ = 524288LLU, + scopeinferred = 2097152LLU, + return_ = 4194304LLU, + returnScope = 8388608LLU, + returninferred = 16777216LLU, + immutable_ = 33554432LLU, + manifest = 134217728LLU, + nodtor = 268435456LLU, + nothrow_ = 536870912LLU, + pure_ = 1073741824LLU, + tls = 2147483648LLU, + alias_ = 4294967296LLU, + shared_ = 8589934592LLU, + gshared = 17179869184LLU, + wild = 34359738368LLU, + property = 68719476736LLU, + safe = 137438953472LLU, + trusted = 274877906944LLU, + system = 549755813888LLU, + ctfe = 1099511627776LLU, + disable = 2199023255552LLU, + result = 4398046511104LLU, + nodefaultctor = 8796093022208LLU, + temp = 17592186044416LLU, + rvalue = 35184372088832LLU, + nogc = 70368744177664LLU, + autoref = 140737488355328LLU, + inference = 281474976710656LLU, + exptemp = 562949953421312LLU, + future = 1125899906842624LLU, + local = 2251799813685248LLU, + live = 4503599627370496LLU, + register_ = 9007199254740992LLU, + volatile_ = 18014398509481984LLU, + safeGroup = 962072674304LLU, + IOR = 268288LLU, + TYPECTOR = 42983227396LLU, + FUNCATTR = 4575000774574080LLU, + visibleStorageClasses = 7954966262857631LLU, + flowThruAggregate = 962072674304LLU, + flowThruFunction = 18446742978991225440LLU, }; -class StructLiteralExp final : public Expression +struct ASTCodegen final { -public: - StructDeclaration* sd; - Array* elements; - Type* stype; - union + using AggregateDeclaration = ::AggregateDeclaration; + using ClassKind = ::ClassKind; + using MangleOverride = ::MangleOverride; + using AliasThis = ::AliasThis; + using AliasDeclarations = ::AliasDeclarations; + using BaseClasses = ::BaseClasses; + using CaseStatements = ::CaseStatements; + using Catches = ::Catches; + using ClassDeclarations = ::ClassDeclarations; + using DesigInits = ::DesigInits; + using Designators = ::Designators; + using Dsymbols = ::Dsymbols; + using DtorDeclarations = ::DtorDeclarations; + using Ensures = ::Ensures; + using Expressions = ::Expressions; + using FuncDeclarations = ::FuncDeclarations; + using GotoCaseStatements = ::GotoCaseStatements; + using GotoStatements = ::GotoStatements; + using Identifiers = ::Identifiers; + using Initializers = ::Initializers; + using Modules = ::Modules; + using Objects = ::Objects; + using Parameters = ::Parameters; + using ReturnStatements = ::ReturnStatements; + using ScopeStatements = ::ScopeStatements; + using SharedStaticDtorDeclarations = ::SharedStaticDtorDeclarations; + using Statements = ::Statements; + using StaticDtorDeclarations = ::StaticDtorDeclarations; + using Strings = ::Strings; + using TemplateInstances = ::TemplateInstances; + using TemplateParameters = ::TemplateParameters; + using Types = ::Types; + using VarDeclarations = ::VarDeclarations; + using AlignDeclaration = ::AlignDeclaration; + using AnonDeclaration = ::AnonDeclaration; + using AttribDeclaration = ::AttribDeclaration; + using CPPMangleDeclaration = ::CPPMangleDeclaration; + using CPPNamespaceDeclaration = ::CPPNamespaceDeclaration; + using ConditionalDeclaration = ::ConditionalDeclaration; + using DeprecatedDeclaration = ::DeprecatedDeclaration; + using ForwardingAttribDeclaration = ::ForwardingAttribDeclaration; + using LinkDeclaration = ::LinkDeclaration; + using MixinDeclaration = ::MixinDeclaration; + using PragmaDeclaration = ::PragmaDeclaration; + using StaticForeachDeclaration = ::StaticForeachDeclaration; + using StaticIfDeclaration = ::StaticIfDeclaration; + using StorageClassDeclaration = ::StorageClassDeclaration; + using UserAttributeDeclaration = ::UserAttributeDeclaration; + using VisibilityDeclaration = ::VisibilityDeclaration; + using Condition = ::Condition; + using DVCondition = ::DVCondition; + using DebugCondition = ::DebugCondition; + using Include = ::Include; + using StaticForeach = ::StaticForeach; + using StaticIfCondition = ::StaticIfCondition; + using VersionCondition = ::VersionCondition; + using BaseClass = ::BaseClass; + using ClassDeclaration = ::ClassDeclaration; + using ClassFlags = ::ClassFlags; + using InterfaceDeclaration = ::InterfaceDeclaration; + using AliasDeclaration = ::AliasDeclaration; + using BitFieldDeclaration = ::BitFieldDeclaration; + using Declaration = ::Declaration; + using MatchAccumulator = ::MatchAccumulator; + using OverDeclaration = ::OverDeclaration; + using SymbolDeclaration = ::SymbolDeclaration; + using ThisDeclaration = ::ThisDeclaration; + using TupleDeclaration = ::TupleDeclaration; + using TypeInfoArrayDeclaration = ::TypeInfoArrayDeclaration; + using TypeInfoAssociativeArrayDeclaration = ::TypeInfoAssociativeArrayDeclaration; + using TypeInfoClassDeclaration = ::TypeInfoClassDeclaration; + using TypeInfoConstDeclaration = ::TypeInfoConstDeclaration; + using TypeInfoDeclaration = ::TypeInfoDeclaration; + using TypeInfoDelegateDeclaration = ::TypeInfoDelegateDeclaration; + using TypeInfoEnumDeclaration = ::TypeInfoEnumDeclaration; + using TypeInfoFunctionDeclaration = ::TypeInfoFunctionDeclaration; + using TypeInfoInterfaceDeclaration = ::TypeInfoInterfaceDeclaration; + using TypeInfoInvariantDeclaration = ::TypeInfoInvariantDeclaration; + using TypeInfoPointerDeclaration = ::TypeInfoPointerDeclaration; + using TypeInfoSharedDeclaration = ::TypeInfoSharedDeclaration; + using TypeInfoStaticArrayDeclaration = ::TypeInfoStaticArrayDeclaration; + using TypeInfoStructDeclaration = ::TypeInfoStructDeclaration; + using TypeInfoTupleDeclaration = ::TypeInfoTupleDeclaration; + using TypeInfoVectorDeclaration = ::TypeInfoVectorDeclaration; + using TypeInfoWildDeclaration = ::TypeInfoWildDeclaration; + using VarDeclaration = ::VarDeclaration; + using EnumDeclaration = ::EnumDeclaration; + using EnumMember = ::EnumMember; + using Import = ::Import; + using ForeachDg = ::ForeachDg; + using Module = ::Module; + using ModuleDeclaration = ::ModuleDeclaration; + using Package = ::Package; + using StructDeclaration = ::StructDeclaration; + using StructFlags = ::StructFlags; + using UnionDeclaration = ::UnionDeclaration; + using AliasAssign = ::AliasAssign; + using ArrayScopeSymbol = ::ArrayScopeSymbol; + using Dsymbol = ::Dsymbol; + using DsymbolTable = ::DsymbolTable; + using ExpressionDsymbol = ::ExpressionDsymbol; + using FieldState = ::FieldState; + using ForwardingScopeDsymbol = ::ForwardingScopeDsymbol; + using OverloadSet = ::OverloadSet; + using PASS = ::PASS; + using ScopeDsymbol = ::ScopeDsymbol; + using SearchOpt = ::SearchOpt; + using SearchOptFlags = ::SearchOptFlags; + using Ungag = ::Ungag; + using Visibility = ::Visibility; + using WithScopeSymbol = ::WithScopeSymbol; + using TemplateAliasParameter = ::TemplateAliasParameter; + using TemplateDeclaration = ::TemplateDeclaration; + using TemplateInstance = ::TemplateInstance; + using TemplateInstanceBox = ::TemplateInstanceBox; + using TemplateMixin = ::TemplateMixin; + using TemplateParameter = ::TemplateParameter; + using TemplatePrevious = ::TemplatePrevious; + using TemplateStats = ::TemplateStats; + using TemplateThisParameter = ::TemplateThisParameter; + using TemplateTupleParameter = ::TemplateTupleParameter; + using TemplateTypeParameter = ::TemplateTypeParameter; + using TemplateValueParameter = ::TemplateValueParameter; + using Tuple = ::Tuple; + using TypeDeduced = ::TypeDeduced; + using DebugSymbol = ::DebugSymbol; + using VersionSymbol = ::VersionSymbol; + using AddAssignExp = ::AddAssignExp; + using AddExp = ::AddExp; + using AddrExp = ::AddrExp; + using AndAssignExp = ::AndAssignExp; + using AndExp = ::AndExp; + using ArgumentList = ::ArgumentList; + using ArrayExp = ::ArrayExp; + using ArrayLengthExp = ::ArrayLengthExp; + using ArrayLiteralExp = ::ArrayLiteralExp; + using AssertExp = ::AssertExp; + using AssignExp = ::AssignExp; + using AssocArrayLiteralExp = ::AssocArrayLiteralExp; + using BinAssignExp = ::BinAssignExp; + using BinExp = ::BinExp; + using BlitExp = ::BlitExp; + using CTFEExp = ::CTFEExp; + using CallExp = ::CallExp; + using CastExp = ::CastExp; + using CatAssignExp = ::CatAssignExp; + using CatDcharAssignExp = ::CatDcharAssignExp; + using CatElemAssignExp = ::CatElemAssignExp; + using CatExp = ::CatExp; + using ClassReferenceExp = ::ClassReferenceExp; + using CmpExp = ::CmpExp; + using ComExp = ::ComExp; + using CommaExp = ::CommaExp; + using ComplexExp = ::ComplexExp; + using CompoundLiteralExp = ::CompoundLiteralExp; + using CondExp = ::CondExp; + using ConstructExp = ::ConstructExp; + using DeclarationExp = ::DeclarationExp; + using DefaultInitExp = ::DefaultInitExp; + using DelegateExp = ::DelegateExp; + using DelegateFuncptrExp = ::DelegateFuncptrExp; + using DelegatePtrExp = ::DelegatePtrExp; + using DeleteExp = ::DeleteExp; + using DivAssignExp = ::DivAssignExp; + using DivExp = ::DivExp; + using DollarExp = ::DollarExp; + using DotExp = ::DotExp; + using DotIdExp = ::DotIdExp; + using DotTemplateExp = ::DotTemplateExp; + using DotTemplateInstanceExp = ::DotTemplateInstanceExp; + using DotTypeExp = ::DotTypeExp; + using DotVarExp = ::DotVarExp; + using DsymbolExp = ::DsymbolExp; + using EqualExp = ::EqualExp; + using ErrorExp = ::ErrorExp; + using Expression = ::Expression; + using FileInitExp = ::FileInitExp; + using FuncExp = ::FuncExp; + using FuncInitExp = ::FuncInitExp; + using GenericExp = ::GenericExp; + using HaltExp = ::HaltExp; + using IdentifierExp = ::IdentifierExp; + using IdentityExp = ::IdentityExp; + using ImportExp = ::ImportExp; + using InExp = ::InExp; + using IndexExp = ::IndexExp; + using IntegerExp = ::IntegerExp; + using IntervalExp = ::IntervalExp; + using IsExp = ::IsExp; + using LineInitExp = ::LineInitExp; + using LogicalExp = ::LogicalExp; + using LoweredAssignExp = ::LoweredAssignExp; + using MemorySet = ::MemorySet; + using MinAssignExp = ::MinAssignExp; + using MinExp = ::MinExp; + using MixinExp = ::MixinExp; + using ModAssignExp = ::ModAssignExp; + using ModExp = ::ModExp; + using Modifiable = ::Modifiable; + using ModifyFlags = ::ModifyFlags; + using ModuleInitExp = ::ModuleInitExp; + using MulAssignExp = ::MulAssignExp; + using MulExp = ::MulExp; + using NegExp = ::NegExp; + using NewAnonClassExp = ::NewAnonClassExp; + using NewExp = ::NewExp; + using NotExp = ::NotExp; + using NullExp = ::NullExp; + using ObjcClassReferenceExp = ::ObjcClassReferenceExp; + using OrAssignExp = ::OrAssignExp; + using OrExp = ::OrExp; + using OverExp = ::OverExp; + using OwnedBy = ::OwnedBy; + using PostExp = ::PostExp; + using PowAssignExp = ::PowAssignExp; + using PowExp = ::PowExp; + using PreExp = ::PreExp; + using PrettyFuncInitExp = ::PrettyFuncInitExp; + using PtrExp = ::PtrExp; + using RealExp = ::RealExp; + using RemoveExp = ::RemoveExp; + using ScopeExp = ::ScopeExp; + using ShlAssignExp = ::ShlAssignExp; + using ShlExp = ::ShlExp; + using ShrAssignExp = ::ShrAssignExp; + using ShrExp = ::ShrExp; + using SliceExp = ::SliceExp; + using StringExp = ::StringExp; + using StructLiteralExp = ::StructLiteralExp; + using SuperExp = ::SuperExp; + using SymOffExp = ::SymOffExp; + using SymbolExp = ::SymbolExp; + using TemplateExp = ::TemplateExp; + using ThisExp = ::ThisExp; + using ThrowExp = ::ThrowExp; + using ThrownExceptionExp = ::ThrownExceptionExp; + using TraitsExp = ::TraitsExp; + using TupleExp = ::TupleExp; + using TypeExp = ::TypeExp; + using TypeidExp = ::TypeidExp; + using UAddExp = ::UAddExp; + using UnaExp = ::UnaExp; + using UshrAssignExp = ::UshrAssignExp; + using UshrExp = ::UshrExp; + using VarExp = ::VarExp; + using VectorArrayExp = ::VectorArrayExp; + using VectorExp = ::VectorExp; + using VoidInitExp = ::VoidInitExp; + using XorAssignExp = ::XorAssignExp; + using XorExp = ::XorExp; + using AttributeViolation = ::AttributeViolation; + using BUILTIN = ::BUILTIN; + using CtorDeclaration = ::CtorDeclaration; + using DtorDeclaration = ::DtorDeclaration; + using Ensure = ::Ensure; + using FuncAliasDeclaration = ::FuncAliasDeclaration; + using FuncDeclaration = ::FuncDeclaration; + using FuncLiteralDeclaration = ::FuncLiteralDeclaration; + using FuncResolveFlag = ::FuncResolveFlag; + using ILS = ::ILS; + using InvariantDeclaration = ::InvariantDeclaration; + using NewDeclaration = ::NewDeclaration; + using NrvoWalker = ::NrvoWalker; + using PostBlitDeclaration = ::PostBlitDeclaration; + using SharedStaticCtorDeclaration = ::SharedStaticCtorDeclaration; + using SharedStaticDtorDeclaration = ::SharedStaticDtorDeclaration; + using StaticCtorDeclaration = ::StaticCtorDeclaration; + using StaticDtorDeclaration = ::StaticDtorDeclaration; + using UnitTestDeclaration = ::UnitTestDeclaration; + using HdrGenState = ::HdrGenState; + using ArrayInitializer = ::ArrayInitializer; + using CInitializer = ::CInitializer; + using DefaultInitializer = ::DefaultInitializer; + using DesigInit = ::DesigInit; + using Designator = ::Designator; + using ErrorInitializer = ::ErrorInitializer; + using ExpInitializer = ::ExpInitializer; + using Initializer = ::Initializer; + using NeedInterpret = ::NeedInterpret; + using StructInitializer = ::StructInitializer; + using VisitInitializer = ::VisitInitializer; + using VoidInitializer = ::VoidInitializer; + using Covariant = ::Covariant; + using DotExpFlag = ::DotExpFlag; + using Parameter = ::Parameter; + using ParameterList = ::ParameterList; + using RET = ::RET; + using ScopeRef = ::ScopeRef; + using TRUSTformat = ::TRUSTformat; + using Type = ::Type; + using TypeAArray = ::TypeAArray; + using TypeArray = ::TypeArray; + using TypeBasic = ::TypeBasic; + using TypeClass = ::TypeClass; + using TypeDArray = ::TypeDArray; + using TypeDelegate = ::TypeDelegate; + using TypeEnum = ::TypeEnum; + using TypeError = ::TypeError; + using TypeFunction = ::TypeFunction; + using TypeIdentifier = ::TypeIdentifier; + using TypeInstance = ::TypeInstance; + using TypeMixin = ::TypeMixin; + using TypeNext = ::TypeNext; + using TypeNoreturn = ::TypeNoreturn; + using TypeNull = ::TypeNull; + using TypePointer = ::TypePointer; + using TypeQualified = ::TypeQualified; + using TypeReference = ::TypeReference; + using TypeReturn = ::TypeReturn; + using TypeSArray = ::TypeSArray; + using TypeSlice = ::TypeSlice; + using TypeStruct = ::TypeStruct; + using TypeTag = ::TypeTag; + using TypeTraits = ::TypeTraits; + using TypeTuple = ::TypeTuple; + using TypeTypeof = ::TypeTypeof; + using TypeVector = ::TypeVector; + using VisitType = ::VisitType; + using Nspace = ::Nspace; + using AsmStatement = ::AsmStatement; + using BreakStatement = ::BreakStatement; + using CaseRangeStatement = ::CaseRangeStatement; + using CaseStatement = ::CaseStatement; + using Catch = ::Catch; + using CompoundAsmStatement = ::CompoundAsmStatement; + using CompoundDeclarationStatement = ::CompoundDeclarationStatement; + using CompoundStatement = ::CompoundStatement; + using ConditionalStatement = ::ConditionalStatement; + using ContinueStatement = ::ContinueStatement; + using DebugStatement = ::DebugStatement; + using DefaultStatement = ::DefaultStatement; + using DoStatement = ::DoStatement; + using DtorExpStatement = ::DtorExpStatement; + using ErrorStatement = ::ErrorStatement; + using ExpStatement = ::ExpStatement; + using ForStatement = ::ForStatement; + using ForeachRangeStatement = ::ForeachRangeStatement; + using ForeachStatement = ::ForeachStatement; + using ForwardingStatement = ::ForwardingStatement; + using GccAsmStatement = ::GccAsmStatement; + using GotoCaseStatement = ::GotoCaseStatement; + using GotoDefaultStatement = ::GotoDefaultStatement; + using GotoStatement = ::GotoStatement; + using IfStatement = ::IfStatement; + using ImportStatement = ::ImportStatement; + using InlineAsmStatement = ::InlineAsmStatement; + using LabelDsymbol = ::LabelDsymbol; + using LabelStatement = ::LabelStatement; + using MixinStatement = ::MixinStatement; + using PeelStatement = ::PeelStatement; + using PragmaStatement = ::PragmaStatement; + using ReturnStatement = ::ReturnStatement; + using ScopeGuardStatement = ::ScopeGuardStatement; + using ScopeStatement = ::ScopeStatement; + using Statement = ::Statement; + using StaticAssertStatement = ::StaticAssertStatement; + using StaticForeachStatement = ::StaticForeachStatement; + using SwitchErrorStatement = ::SwitchErrorStatement; + using SwitchStatement = ::SwitchStatement; + using SynchronizedStatement = ::SynchronizedStatement; + using ThrowStatement = ::ThrowStatement; + using TryCatchStatement = ::TryCatchStatement; + using TryFinallyStatement = ::TryFinallyStatement; + using UnrolledLoopStatement = ::UnrolledLoopStatement; + using VisitStatement = ::VisitStatement; + using WhileStatement = ::WhileStatement; + using WithStatement = ::WithStatement; + using StaticAssert = ::StaticAssert; + using UnionExp = ::UnionExp; + using emplaceExp = ::emplaceExp; + typedef UserAttributeDeclaration* UserAttributeDeclaration; + typedef Ensure Ensure; + typedef ErrorExp* ErrorExp; + typedef MODFlags MODFlags; + typedef Type* Type; + typedef Parameter* Parameter; + typedef ParameterList ParameterList; + typedef VarArg VarArg; + typedef STC STC; + typedef Dsymbol* Dsymbol; + typedef Array Dsymbols; + typedef Visibility Visibility; + typedef SearchOpt SearchOpt; + typedef PASS PASS; + ASTCodegen() { - Symbol* sym; - StructLiteralExp* inlinecopy; - }; - StructLiteralExp* origin; - uint8_t stageflags; - bool useStaticInit; - bool isOriginal; - OwnedBy ownedByCtfe; - static StructLiteralExp* create(const Loc& loc, StructDeclaration* sd, void* elements, Type* stype = nullptr); - bool equals(const RootObject* const o) const override; - StructLiteralExp* syntaxCopy() override; - void accept(Visitor* v) override; -}; - -class CompoundLiteralExp final : public Expression -{ -public: - Initializer* initializer; - void accept(Visitor* v) override; + } }; -class TypeExp final : public Expression +class Visitor : public ParseTimeVisitor { public: - bool parens; - TypeExp* syntaxCopy() override; - bool checkType() override; - bool checkValue() override; - void accept(Visitor* v) override; + using ParseTimeVisitor::visit; + virtual void visit(ErrorStatement* s); + virtual void visit(PeelStatement* s); + virtual void visit(UnrolledLoopStatement* s); + virtual void visit(SwitchErrorStatement* s); + virtual void visit(DebugStatement* s); + virtual void visit(DtorExpStatement* s); + virtual void visit(ForwardingStatement* s); + virtual void visit(OverloadSet* s); + virtual void visit(LabelDsymbol* s); + virtual void visit(WithScopeSymbol* s); + virtual void visit(ArrayScopeSymbol* s); + virtual void visit(OverDeclaration* s); + virtual void visit(SymbolDeclaration* s); + virtual void visit(ForwardingAttribDeclaration* s); + virtual void visit(ThisDeclaration* s); + virtual void visit(TypeInfoDeclaration* s); + virtual void visit(TypeInfoStructDeclaration* s); + virtual void visit(TypeInfoClassDeclaration* s); + virtual void visit(TypeInfoInterfaceDeclaration* s); + virtual void visit(TypeInfoPointerDeclaration* s); + virtual void visit(TypeInfoArrayDeclaration* s); + virtual void visit(TypeInfoStaticArrayDeclaration* s); + virtual void visit(TypeInfoAssociativeArrayDeclaration* s); + virtual void visit(TypeInfoEnumDeclaration* s); + virtual void visit(TypeInfoFunctionDeclaration* s); + virtual void visit(TypeInfoDelegateDeclaration* s); + virtual void visit(TypeInfoTupleDeclaration* s); + virtual void visit(TypeInfoConstDeclaration* s); + virtual void visit(TypeInfoInvariantDeclaration* s); + virtual void visit(TypeInfoSharedDeclaration* s); + virtual void visit(TypeInfoWildDeclaration* s); + virtual void visit(TypeInfoVectorDeclaration* s); + virtual void visit(FuncAliasDeclaration* s); + virtual void visit(ErrorInitializer* i); + virtual void visit(ErrorExp* e); + virtual void visit(ComplexExp* e); + virtual void visit(StructLiteralExp* e); + virtual void visit(CompoundLiteralExp* e); + virtual void visit(ObjcClassReferenceExp* e); + virtual void visit(SymOffExp* e); + virtual void visit(OverExp* e); + virtual void visit(HaltExp* e); + virtual void visit(DotTemplateExp* e); + virtual void visit(DotVarExp* e); + virtual void visit(DelegateExp* e); + virtual void visit(DotTypeExp* e); + virtual void visit(VectorExp* e); + virtual void visit(VectorArrayExp* e); + virtual void visit(SliceExp* e); + virtual void visit(ArrayLengthExp* e); + virtual void visit(DelegatePtrExp* e); + virtual void visit(DelegateFuncptrExp* e); + virtual void visit(DotExp* e); + virtual void visit(IndexExp* e); + virtual void visit(ConstructExp* e); + virtual void visit(BlitExp* e); + virtual void visit(RemoveExp* e); + virtual void visit(ClassReferenceExp* e); + virtual void visit(VoidInitExp* e); + virtual void visit(ThrownExceptionExp* e); + virtual void visit(LoweredAssignExp* e); }; -class ScopeExp final : public Expression +class StoppableVisitor : public Visitor { public: - ScopeDsymbol* sds; - ScopeExp* syntaxCopy() override; - bool checkType() override; - bool checkValue() override; - void accept(Visitor* v) override; + using Visitor::visit; + bool stop; }; -class TemplateExp final : public Expression +struct TargetC final { -public: - TemplateDeclaration* td; - FuncDeclaration* fd; - bool isLvalue() override; - bool checkType() override; - bool checkValue() override; - void accept(Visitor* v) override; -}; + enum class Runtime : uint8_t + { + Unspecified = 0u, + Bionic = 1u, + DigitalMars = 2u, + Glibc = 3u, + Microsoft = 4u, + Musl = 5u, + Newlib = 6u, + UClibc = 7u, + WASI = 8u, + }; -class NewExp final : public Expression -{ -public: - Expression* thisexp; - Type* newtype; - Array* arguments; - Array* names; - Expression* argprefix; - CtorDeclaration* member; - bool onstack; - bool thrownew; - Expression* lowering; - static NewExp* create(const Loc& loc, Expression* thisexp, Type* newtype, Array* arguments); - NewExp* syntaxCopy() override; - void accept(Visitor* v) override; -}; + enum class BitFieldStyle : uint8_t + { + Unspecified = 0u, + DM = 1u, + MS = 2u, + Gcc_Clang = 3u, + }; -class NewAnonClassExp final : public Expression -{ -public: - Expression* thisexp; - ClassDeclaration* cd; - Array* arguments; - NewAnonClassExp* syntaxCopy() override; - void accept(Visitor* v) override; + bool crtDestructorsSupported; + uint8_t boolsize; + uint8_t shortsize; + uint8_t intsize; + uint8_t longsize; + uint8_t long_longsize; + uint8_t long_doublesize; + uint8_t wchar_tsize; + Runtime runtime; + BitFieldStyle bitFieldStyle; + TargetC() : + crtDestructorsSupported(true), + boolsize(), + shortsize(), + intsize(), + longsize(), + long_longsize(), + long_doublesize(), + wchar_tsize() + { + } + TargetC(bool crtDestructorsSupported, uint8_t boolsize = 0u, uint8_t shortsize = 0u, uint8_t intsize = 0u, uint8_t longsize = 0u, uint8_t long_longsize = 0u, uint8_t long_doublesize = 0u, uint8_t wchar_tsize = 0u, Runtime runtime = (Runtime)0u, BitFieldStyle bitFieldStyle = (BitFieldStyle)0u) : + crtDestructorsSupported(crtDestructorsSupported), + boolsize(boolsize), + shortsize(shortsize), + intsize(intsize), + longsize(longsize), + long_longsize(long_longsize), + long_doublesize(long_doublesize), + wchar_tsize(wchar_tsize), + runtime(runtime), + bitFieldStyle(bitFieldStyle) + {} }; -class SymbolExp : public Expression +struct TargetCPP final { -public: - Declaration* var; - Dsymbol* originalScope; - bool hasOverloads; - void accept(Visitor* v) override; -}; + enum class Runtime : uint8_t + { + Unspecified = 0u, + Clang = 1u, + DigitalMars = 2u, + Gcc = 3u, + Microsoft = 4u, + Sun = 5u, + }; -class SymOffExp final : public SymbolExp -{ -public: - dinteger_t offset; - Optional toBool() override; - void accept(Visitor* v) override; + bool reverseOverloads; + bool exceptions; + bool twoDtorInVtable; + bool splitVBasetable; + bool wrapDtorInExternD; + Runtime runtime; + const char* toMangle(Dsymbol* s); + const char* typeInfoMangle(ClassDeclaration* cd); + const char* thunkMangle(FuncDeclaration* fd, int32_t offset); + const char* typeMangle(Type* t); + Type* parameterType(Type* t); + bool fundamentalType(const Type* const t, bool& isFundamental); + uint32_t derivedClassOffset(ClassDeclaration* baseClass); + TargetCPP() : + reverseOverloads(), + exceptions(), + twoDtorInVtable(), + splitVBasetable(), + wrapDtorInExternD() + { + } + TargetCPP(bool reverseOverloads, bool exceptions = false, bool twoDtorInVtable = false, bool splitVBasetable = false, bool wrapDtorInExternD = false, Runtime runtime = (Runtime)0u) : + reverseOverloads(reverseOverloads), + exceptions(exceptions), + twoDtorInVtable(twoDtorInVtable), + splitVBasetable(splitVBasetable), + wrapDtorInExternD(wrapDtorInExternD), + runtime(runtime) + {} }; -class VarExp final : public SymbolExp +struct TargetObjC final { -public: - bool delegateWasExtracted; - static VarExp* create(const Loc& loc, Declaration* var, bool hasOverloads = true); - bool equals(const RootObject* const o) const override; - bool isLvalue() override; - void accept(Visitor* v) override; + bool supported; + TargetObjC() : + supported() + { + } + TargetObjC(bool supported) : + supported(supported) + {} }; -class OverExp final : public Expression +enum class CPU : uint8_t { -public: - OverloadSet* vars; - bool isLvalue() override; - void accept(Visitor* v) override; + x87 = 0u, + mmx = 1u, + sse = 2u, + sse2 = 3u, + sse3 = 4u, + ssse3 = 5u, + sse4_1 = 6u, + sse4_2 = 7u, + avx = 8u, + avx2 = 9u, + avx512 = 10u, + baseline = 11u, + native = 12u, }; -class FuncExp final : public Expression +enum class ErrorKind { -public: - FuncLiteralDeclaration* fd; - TemplateDeclaration* td; - TOK tok; - bool equals(const RootObject* const o) const override; - FuncExp* syntaxCopy() override; - const char* toChars() const override; - bool checkType() override; - bool checkValue() override; - void accept(Visitor* v) override; + warning = 0, + deprecation = 1, + error = 2, + tip = 3, + message = 4, }; -class DeclarationExp final : public Expression -{ -public: - Dsymbol* declaration; - DeclarationExp* syntaxCopy() override; - bool hasCode() override; - void accept(Visitor* v) override; -}; +typedef _d_real longdouble; -class TypeidExp final : public Expression +typedef uint64_t uint64_t; + +class AggregateDeclaration : public ScopeDsymbol { public: - RootObject* obj; - TypeidExp* syntaxCopy() override; + Type* type; + StorageClass storage_class; + uint32_t structsize; + uint32_t alignsize; + Array fields; + Dsymbol* deferred; + ClassKind classKind; + CPPMANGLE cppmangle; + MangleOverride* pMangleOverride; + Dsymbol* enclosing; + VarDeclaration* vthis; + VarDeclaration* vthis2; + Array invs; + FuncDeclaration* inv; + Dsymbol* ctor; + CtorDeclaration* defaultCtor; + AliasThis* aliasthis; + Array userDtors; + DtorDeclaration* aggrDtor; + DtorDeclaration* dtor; + DtorDeclaration* tidtor; + DtorDeclaration* fieldDtor; + Expression* getRTInfo; + Visibility visibility; + bool noDefaultCtor; + bool disableNew; + Sizeok sizeok; + virtual Scope* newScope(Scope* sc); + virtual void finalizeSize() = 0; + uinteger_t size(const Loc& loc) final override; + bool fill(const Loc& loc, Array& elements, bool ctorinit); + Type* getType() final override; + bool isDeprecated() const final override; + bool isNested() const; + bool isExport() const final override; + Visibility visible() final override; + Type* handleType(); + bool hasInvariant(); + void* sinit; + AggregateDeclaration* isAggregateDeclaration() final override; void accept(Visitor* v) override; }; -class TraitsExp final : public Expression +class AliasThis final : public Dsymbol { public: Identifier* ident; - Array* args; - TraitsExp* syntaxCopy() override; + Dsymbol* sym; + bool isDeprecated_; + AliasThis* syntaxCopy(Dsymbol* s) override; + const char* kind() const override; + AliasThis* isAliasThis(); void accept(Visitor* v) override; + bool isDeprecated() const override; }; -class HaltExp final : public Expression -{ -public: - void accept(Visitor* v) override; -}; +extern TypeTuple* toArgTypes_x86(Type* t); -class IsExp final : public Expression -{ -public: - Type* targ; - Identifier* id; - Type* tspec; - Array* parameters; - TOK tok; - TOK tok2; - IsExp* syntaxCopy() override; - void accept(Visitor* v) override; -}; +extern TypeTuple* toArgTypes_sysv_x64(Type* t); -class UnaExp : public Expression -{ -public: - Expression* e1; - UnaExp* syntaxCopy() override; - void setNoderefOperand(); - void accept(Visitor* v) override; -}; +extern TypeTuple* toArgTypes_aarch64(Type* t); -class BinExp : public Expression +extern bool isHFVA(Type* t, int32_t maxNumElements = 4, Type** rewriteType = nullptr); + +struct structalign_t final { +private: + uint16_t value; + bool pack; public: - Expression* e1; - Expression* e2; - Type* att1; - Type* att2; - BinExp* syntaxCopy() override; - void setNoderefOperands(); - void accept(Visitor* v) override; + bool isDefault() const; + void setDefault(); + bool isUnknown() const; + void setUnknown(); + void set(uint32_t value); + uint32_t get() const; + bool isPack() const; + void setPack(bool pack); + structalign_t() : + value(0u), + pack() + { + } + structalign_t(uint16_t value, bool pack = false) : + value(value), + pack(pack) + {} }; -class BinAssignExp : public BinExp +class AttribDeclaration : public Dsymbol { public: - bool isLvalue() final override; + Array* decl; + virtual Array* include(Scope* sc); + virtual Scope* newScope(Scope* sc); + void addComment(const char* comment) override; + const char* kind() const override; + bool oneMember(Dsymbol** ps, Identifier* ident) override; + void setFieldOffset(AggregateDeclaration* ad, FieldState& fieldState, bool isunion) override; + bool hasPointers() final override; + bool hasStaticCtorOrDtor() final override; + void checkCtorConstInit() final override; + void addObjcSymbols(Array* classes, Array* categories) final override; + AttribDeclaration* isAttribDeclaration() override; void accept(Visitor* v) override; }; -class MixinExp final : public Expression +class StorageClassDeclaration : public AttribDeclaration { public: - Array* exps; - MixinExp* syntaxCopy() override; - bool equals(const RootObject* const o) const override; + StorageClass stc; + StorageClassDeclaration* syntaxCopy(Dsymbol* s) override; + Scope* newScope(Scope* sc) override; + bool oneMember(Dsymbol** ps, Identifier* ident) final override; + StorageClassDeclaration* isStorageClassDeclaration() override; void accept(Visitor* v) override; }; -class ImportExp final : public UnaExp +class DeprecatedDeclaration final : public StorageClassDeclaration { public: + Expression* msg; + const char* msgstr; + DeprecatedDeclaration* syntaxCopy(Dsymbol* s) override; + Scope* newScope(Scope* sc) override; void accept(Visitor* v) override; }; -class AssertExp final : public UnaExp +class LinkDeclaration final : public AttribDeclaration { public: - Expression* msg; - AssertExp* syntaxCopy() override; + LINK linkage; + static LinkDeclaration* create(const Loc& loc, LINK p, Array* decl); + LinkDeclaration* syntaxCopy(Dsymbol* s) override; + Scope* newScope(Scope* sc) override; + const char* toChars() const override; void accept(Visitor* v) override; }; -class ThrowExp final : public UnaExp +class CPPMangleDeclaration final : public AttribDeclaration { public: - ThrowExp* syntaxCopy() override; + CPPMANGLE cppmangle; + CPPMangleDeclaration* syntaxCopy(Dsymbol* s) override; + Scope* newScope(Scope* sc) override; + const char* toChars() const override; void accept(Visitor* v) override; }; -class DotIdExp final : public UnaExp +class CPPNamespaceDeclaration final : public AttribDeclaration { public: - Identifier* ident; - bool noderef; - bool wantsym; - bool arrow; - static DotIdExp* create(const Loc& loc, Expression* e, Identifier* ident); + Expression* exp; + CPPNamespaceDeclaration* syntaxCopy(Dsymbol* s) override; + Scope* newScope(Scope* sc) override; + const char* toChars() const override; void accept(Visitor* v) override; + CPPNamespaceDeclaration* isCPPNamespaceDeclaration() override; }; -class DotTemplateExp final : public UnaExp +class VisibilityDeclaration final : public AttribDeclaration { public: - TemplateDeclaration* td; - bool checkType() override; - bool checkValue() override; + Visibility visibility; + _d_dynamicArray< Identifier* > pkg_identifiers; + VisibilityDeclaration* syntaxCopy(Dsymbol* s) override; + Scope* newScope(Scope* sc) override; + const char* kind() const override; + const char* toPrettyChars(bool __param_0_) override; + VisibilityDeclaration* isVisibilityDeclaration() override; void accept(Visitor* v) override; }; -class DotVarExp final : public UnaExp +class AlignDeclaration final : public AttribDeclaration { public: - Declaration* var; - bool hasOverloads; - bool isLvalue() override; + Array* exps; + structalign_t salign; + AlignDeclaration* syntaxCopy(Dsymbol* s) override; + Scope* newScope(Scope* sc) override; void accept(Visitor* v) override; }; -class DotTemplateInstanceExp final : public UnaExp +class AnonDeclaration final : public AttribDeclaration { public: - TemplateInstance* ti; - DotTemplateInstanceExp* syntaxCopy() override; - bool checkType() override; - bool checkValue() override; + bool isunion; + int32_t sem; + uint32_t anonoffset; + uint32_t anonstructsize; + uint32_t anonalignsize; + AnonDeclaration* syntaxCopy(Dsymbol* s) override; + void setFieldOffset(AggregateDeclaration* ad, FieldState& fieldState, bool isunion) override; + const char* kind() const override; + AnonDeclaration* isAnonDeclaration() override; void accept(Visitor* v) override; }; -class DelegateExp final : public UnaExp +class PragmaDeclaration final : public AttribDeclaration { public: - FuncDeclaration* func; - bool hasOverloads; - VarDeclaration* vthis2; + Array* args; + PragmaDeclaration* syntaxCopy(Dsymbol* s) override; + Scope* newScope(Scope* sc) override; + const char* kind() const override; void accept(Visitor* v) override; }; -class DotTypeExp final : public UnaExp +class ConditionalDeclaration : public AttribDeclaration { public: - Dsymbol* sym; + Condition* condition; + Array* elsedecl; + ConditionalDeclaration* syntaxCopy(Dsymbol* s) override; + bool oneMember(Dsymbol** ps, Identifier* ident) final override; + Array* include(Scope* sc) override; + void addComment(const char* comment) final override; void accept(Visitor* v) override; }; -class CallExp final : public UnaExp +class StaticIfDeclaration final : public ConditionalDeclaration { public: - Array* arguments; - Array* names; - FuncDeclaration* f; - bool directcall; - bool inDebugStatement; - bool ignoreAttributes; - bool isUfcsRewrite; - VarDeclaration* vthis2; - static CallExp* create(const Loc& loc, Expression* e, Array* exps); - static CallExp* create(const Loc& loc, Expression* e); - static CallExp* create(const Loc& loc, Expression* e, Expression* earg1); - static CallExp* create(const Loc& loc, FuncDeclaration* fd, Expression* earg1); - CallExp* syntaxCopy() override; - bool isLvalue() override; - void accept(Visitor* v) override; -}; - -class AddrExp final : public UnaExp -{ + ScopeDsymbol* scopesym; +private: + bool addisdone; + bool onStack; public: + StaticIfDeclaration* syntaxCopy(Dsymbol* s) override; + Array* include(Scope* sc) override; + const char* kind() const override; + StaticIfDeclaration* isStaticIfDeclaration() override; void accept(Visitor* v) override; }; -class PtrExp final : public UnaExp +class StaticForeachDeclaration final : public AttribDeclaration { public: - bool isLvalue() override; + StaticForeach* sfe; + ScopeDsymbol* scopesym; + bool onStack; + bool cached; + Array* cache; + StaticForeachDeclaration* syntaxCopy(Dsymbol* s) override; + bool oneMember(Dsymbol** ps, Identifier* ident) override; + Array* include(Scope* sc) override; + void addComment(const char* comment) override; + const char* kind() const override; void accept(Visitor* v) override; }; -class NegExp final : public UnaExp +class ForwardingAttribDeclaration final : public AttribDeclaration { public: + ForwardingScopeDsymbol* sym; + ForwardingAttribDeclaration(Array* decl); + Scope* newScope(Scope* sc) override; + ForwardingAttribDeclaration* isForwardingAttribDeclaration() override; void accept(Visitor* v) override; }; -class UAddExp final : public UnaExp +class MixinDeclaration final : public AttribDeclaration { public: + Array* exps; + ScopeDsymbol* scopesym; + bool compiled; + MixinDeclaration* syntaxCopy(Dsymbol* s) override; + const char* kind() const override; + MixinDeclaration* isMixinDeclaration() override; void accept(Visitor* v) override; }; -class ComExp final : public UnaExp +class UserAttributeDeclaration final : public AttribDeclaration { public: + Array* atts; + UserAttributeDeclaration* syntaxCopy(Dsymbol* s) override; + Scope* newScope(Scope* sc) override; + Array* getAttributes(); + const char* kind() const override; void accept(Visitor* v) override; + static bool isGNUABITag(Expression* e); + static void checkGNUABITag(Dsymbol* sym, LINK linkage); }; -class NotExp final : public UnaExp +extern BUILTIN isBuiltin(FuncDeclaration* fd); + +extern Expression* eval_builtin(const Loc& loc, FuncDeclaration* fd, Array* arguments); + +extern bool includeImports; + +extern Array includeModulePatterns; + +extern Array compiledImports; + +struct Compiler final { -public: - void accept(Visitor* v) override; + static Expression* paintAsType(UnionExp* pue, Expression* e, Type* type); + static void onParseModule(Module* m); + static bool onImport(Module* m); + Compiler() + { + } }; -class DeleteExp final : public UnaExp +class Condition : public ASTNode { public: - bool isRAII; + Loc loc; + Include inc; + DYNCAST dyncast() const final override; + virtual Condition* syntaxCopy() = 0; + virtual int32_t include(Scope* sc) = 0; + virtual DebugCondition* isDebugCondition(); + virtual VersionCondition* isVersionCondition(); + virtual StaticIfCondition* isStaticIfCondition(); void accept(Visitor* v) override; }; -class CastExp final : public UnaExp +class StaticForeach final : public RootObject { public: - Type* to; - uint8_t mod; - CastExp* syntaxCopy() override; - bool isLvalue() override; - void accept(Visitor* v) override; + Loc loc; + ForeachStatement* aggrfe; + ForeachRangeStatement* rangefe; + bool needExpansion; }; -class VectorExp final : public UnaExp +class DVCondition : public Condition { public: - TypeVector* to; - uint32_t dim; - OwnedBy ownedByCtfe; - static VectorExp* create(const Loc& loc, Expression* e, Type* t); - VectorExp* syntaxCopy() override; + uint32_t level; + Identifier* ident; + Module* mod; + DVCondition* syntaxCopy() final override; void accept(Visitor* v) override; }; -class VectorArrayExp final : public UnaExp +class DebugCondition final : public DVCondition { public: - bool isLvalue() override; + static void addGlobalIdent(const char* ident); + int32_t include(Scope* sc) override; + DebugCondition* isDebugCondition() override; void accept(Visitor* v) override; + const char* toChars() const override; }; -class SliceExp final : public UnaExp +class VersionCondition final : public DVCondition { public: - Expression* upr; - Expression* lwr; - VarDeclaration* lengthVar; - bool upperIsInBounds() const; - bool upperIsInBounds(bool v); - bool lowerIsLessThanUpper() const; - bool lowerIsLessThanUpper(bool v); - bool arrayop() const; - bool arrayop(bool v); -private: - uint8_t bitFields; -public: - SliceExp* syntaxCopy() override; - bool isLvalue() override; - Optional toBool() override; + static void addGlobalIdent(const char* ident); + static void addPredefinedGlobalIdent(const char* ident); + int32_t include(Scope* sc) override; + VersionCondition* isVersionCondition() override; void accept(Visitor* v) override; + const char* toChars() const override; }; -class ArrayLengthExp final : public UnaExp +class StaticIfCondition final : public Condition { public: + Expression* exp; + StaticIfCondition* syntaxCopy() override; + int32_t include(Scope* sc) override; void accept(Visitor* v) override; + StaticIfCondition* isStaticIfCondition() override; + const char* toChars() const override; }; -class ArrayExp final : public UnaExp +extern const char* toCppMangleItanium(Dsymbol* s); + +extern const char* cppTypeInfoMangleItanium(Dsymbol* s); + +extern const char* cppThunkMangleItanium(FuncDeclaration* fd, int32_t offset); + +extern const char* toCppMangleMSVC(Dsymbol* s); + +extern const char* cppTypeInfoMangleMSVC(Dsymbol* s); + +extern const char* toCppMangleDMC(Dsymbol* s); + +extern const char* cppTypeInfoMangleDMC(Dsymbol* s); + +extern FileName preprocess(FileName csrcfile, const Loc& loc, bool& ifile, OutBuffer* defines); + +extern MATCH implicitConvTo(Expression* e, Type* t); + +struct BaseClass final { -public: - Array* arguments; - size_t currentDimension; - VarDeclaration* lengthVar; - ArrayExp* syntaxCopy() override; - bool isLvalue() override; - void accept(Visitor* v) override; + Type* type; + ClassDeclaration* sym; + uint32_t offset; + Array vtbl; + _d_dynamicArray< BaseClass > baseInterfaces; + bool fillVtbl(ClassDeclaration* cd, Array* vtbl, int32_t newinstance); + BaseClass() : + type(), + sym(), + offset(), + vtbl(), + baseInterfaces() + { + } }; -class DotExp final : public BinExp +class ClassDeclaration : public AggregateDeclaration { public: + static ClassDeclaration* object; + static ClassDeclaration* throwable; + static ClassDeclaration* exception; + static ClassDeclaration* errorException; + static ClassDeclaration* cpp_type_info_ptr; + ClassDeclaration* baseClass; + FuncDeclaration* staticCtor; + FuncDeclaration* staticDtor; + Array vtbl; + Array vtblFinal; + Array* baseclasses; + _d_dynamicArray< BaseClass* > interfaces; + Array* vtblInterfaces; + TypeInfoClassDeclaration* vclassinfo; + bool com; + bool stack; + int32_t cppDtorVtblIndex; + bool inuse; + ThreeState isabstract; + Baseok baseok; + ObjcClassDeclaration objc; + Symbol* cpp_type_info_ptr_sym; + static ClassDeclaration* create(const Loc& loc, Identifier* id, Array* baseclasses, Array* members, bool inObject); + const char* toPrettyChars(bool qualifyTypes = false) override; + ClassDeclaration* syntaxCopy(Dsymbol* s) override; + Scope* newScope(Scope* sc) override; + enum : int32_t { OFFSET_RUNTIME = 1985229328 }; + + enum : int32_t { OFFSET_FWDREF = 1985229329 }; + + virtual bool isBaseOf(ClassDeclaration* cd, int32_t* poffset); + bool isBaseInfoComplete() const; + void finalizeSize() final override; + bool hasMonitor(); + bool isFuncHidden(FuncDeclaration* fd); + bool isCOMclass() const; + virtual bool isCOMinterface() const; + bool isCPPclass() const; + virtual bool isCPPinterface() const; + bool isAbstract(); + virtual int32_t vtblOffset() const; + const char* kind() const override; + void addObjcSymbols(Array* classes, Array* categories) final override; + Dsymbol* vtblsym; + Dsymbol* vtblSymbol(); + ClassDeclaration* isClassDeclaration() final override; void accept(Visitor* v) override; }; -class CommaExp final : public BinExp +class InterfaceDeclaration final : public ClassDeclaration { public: - const bool isGenerated; - bool allowCommaExp; - bool isLvalue() override; - Optional toBool() override; + InterfaceDeclaration* syntaxCopy(Dsymbol* s) override; + Scope* newScope(Scope* sc) override; + bool isBaseOf(ClassDeclaration* cd, int32_t* poffset) override; + const char* kind() const override; + int32_t vtblOffset() const override; + bool isCPPinterface() const override; + bool isCOMinterface() const override; + InterfaceDeclaration* isInterfaceDeclaration() override; void accept(Visitor* v) override; - static void allow(Expression* exp); }; -class IntervalExp final : public Expression -{ -public: - Expression* lwr; - Expression* upr; - Expression* syntaxCopy() override; - void accept(Visitor* v) override; -}; +extern void ObjectNotFound(Identifier* id); -class DelegatePtrExp final : public UnaExp +class Declaration : public Dsymbol { public: - bool isLvalue() override; - void accept(Visitor* v) override; -}; + Type* type; + Type* originalType; + StorageClass storage_class; + Visibility visibility; + LINK _linkage; + int16_t inuse; + uint8_t adFlags; + enum : int32_t { wasRead = 1 }; -class DelegateFuncptrExp final : public UnaExp -{ -public: - bool isLvalue() override; - void accept(Visitor* v) override; -}; + enum : int32_t { ignoreRead = 2 }; -class IndexExp final : public BinExp -{ -public: - VarDeclaration* lengthVar; - bool modifiable; - bool indexIsInBounds; - IndexExp* syntaxCopy() override; - bool isLvalue() override; - void accept(Visitor* v) override; -}; + enum : int32_t { nounderscore = 4 }; -class PostExp final : public BinExp -{ -public: - void accept(Visitor* v) override; -}; + enum : int32_t { hidden = 8 }; -class PreExp final : public UnaExp -{ -public: + Symbol* isym; + _d_dynamicArray< const char > mangleOverride; + const char* kind() const override; + uinteger_t size(const Loc& loc) final override; + bool isStatic() const; + LINK resolvedLinkage() const; + virtual bool isDelete(); + virtual bool isDataseg(); + virtual bool isThreadlocal(); + virtual bool isCodeseg() const; + bool isFinal() const; + virtual bool isAbstract(); + bool isConst() const; + bool isImmutable() const; + bool isWild() const; + bool isAuto() const; + bool isScope() const; + bool isReturn() const; + bool isSynchronized() const; + bool isParameter() const; + bool isDeprecated() const final override; + bool isDisabled() const; + bool isOverride() const; + bool isResult() const; + bool isField() const; + bool isIn() const; + bool isOut() const; + bool isRef() const; + bool isReference() const; + bool isFuture() const; + Visibility visible() final override; + Declaration* isDeclaration() final override; void accept(Visitor* v) override; }; -class AssignExp : public BinExp +class TupleDeclaration final : public Declaration { public: - MemorySet memset; - AssignExp(const Loc& loc, EXP tok, Expression* e1, Expression* e2); - bool isLvalue() final override; + Array* objects; + TypeTuple* tupletype; + bool isexp; + bool building; + TupleDeclaration* syntaxCopy(Dsymbol* s) override; + const char* kind() const override; + Type* getType() override; + Dsymbol* toAlias2() override; + bool needThis() override; + TupleDeclaration* isTupleDeclaration() override; void accept(Visitor* v) override; }; -class LoweredAssignExp final : public AssignExp +class AliasDeclaration final : public Declaration { public: - Expression* lowering; - const char* toChars() const override; + Dsymbol* aliassym; + Dsymbol* overnext; + Dsymbol* _import_; + static AliasDeclaration* create(const Loc& loc, Identifier* id, Type* type); + AliasDeclaration* syntaxCopy(Dsymbol* s) override; + bool overloadInsert(Dsymbol* s) override; + const char* kind() const override; + Type* getType() override; + Dsymbol* toAlias() override; + Dsymbol* toAlias2() override; + bool isOverloadable() const override; + AliasDeclaration* isAliasDeclaration() override; void accept(Visitor* v) override; }; -class ConstructExp final : public AssignExp +class OverDeclaration final : public Declaration { public: + Dsymbol* overnext; + Dsymbol* aliassym; + const char* kind() const override; + bool equals(const RootObject* const o) const override; + bool overloadInsert(Dsymbol* s) override; + bool isOverloadable() const override; + Dsymbol* isUnique(); + OverDeclaration* isOverDeclaration() override; void accept(Visitor* v) override; }; -class BlitExp final : public AssignExp +class VarDeclaration : public Declaration { public: - void accept(Visitor* v) override; -}; + Initializer* _init; + Array nestedrefs; + TupleDeclaration* aliasTuple; + VarDeclaration* lastVar; + Expression* edtor; + IntRange* range; + Array* maybes; + uint32_t endlinnum; + uint32_t offset; + uint32_t sequenceNumber; + structalign_t alignment; + enum : uint32_t { AdrOnStackNone = 4294967295u }; -class AddAssignExp final : public BinAssignExp -{ + uint32_t ctfeAdrOnStack; + bool isargptr() const; + bool isargptr(bool v); + bool ctorinit() const; + bool ctorinit(bool v); + bool iscatchvar() const; + bool iscatchvar(bool v); + bool isowner() const; + bool isowner(bool v); + bool setInCtorOnly() const; + bool setInCtorOnly(bool v); + bool onstack() const; + bool onstack(bool v); + bool overlapped() const; + bool overlapped(bool v); + bool overlapUnsafe() const; + bool overlapUnsafe(bool v); + bool maybeScope() const; + bool maybeScope(bool v); + bool doNotInferReturn() const; + bool doNotInferReturn(bool v); + bool isArgDtorVar() const; + bool isArgDtorVar(bool v); + bool isCmacro() const; + bool isCmacro(bool v); + bool dllImport() const; + bool dllImport(bool v); + bool dllExport() const; + bool dllExport(bool v); + bool inClosure() const; + bool inClosure(bool v); + bool inAlignSection() const; + bool inAlignSection(bool v); + bool systemInferred() const; + bool systemInferred(bool v); +private: + uint32_t bitFields; public: + int8_t canassign; + uint8_t isdataseg; + static VarDeclaration* create(const Loc& loc, Type* type, Identifier* ident, Initializer* _init, StorageClass storage_class = static_cast(STC::undefined_)); + VarDeclaration* syntaxCopy(Dsymbol* s) override; + void setFieldOffset(AggregateDeclaration* ad, FieldState& fieldState, bool isunion) override; + const char* kind() const override; + AggregateDeclaration* isThis() final override; + bool needThis() final override; + bool isExport() const final override; + bool isImportedSymbol() const final override; + bool isCtorinit() const; + bool isDataseg() final override; + bool isThreadlocal() final override; + bool isCTFE(); + bool isOverlappedWith(VarDeclaration* v); + bool hasPointers() final override; + bool canTakeAddressOf(); + bool needsScopeDtor(); + void checkCtorConstInit() final override; + Dsymbol* toAlias() final override; + VarDeclaration* isVarDeclaration() final override; void accept(Visitor* v) override; }; -class MinAssignExp final : public BinAssignExp +class BitFieldDeclaration : public VarDeclaration { public: + Expression* width; + uint32_t fieldWidth; + uint32_t bitOffset; + BitFieldDeclaration* syntaxCopy(Dsymbol* s) override; + BitFieldDeclaration* isBitFieldDeclaration() final override; void accept(Visitor* v) override; + uint64_t getMinMax(Identifier* id); + void setFieldOffset(AggregateDeclaration* ad, FieldState& fieldState, bool isunion) final override; }; -class MulAssignExp final : public BinAssignExp +class SymbolDeclaration final : public Declaration { public: + AggregateDeclaration* dsym; + SymbolDeclaration* isSymbolDeclaration() override; void accept(Visitor* v) override; }; -class DivAssignExp final : public BinAssignExp +class TypeInfoDeclaration : public VarDeclaration { public: + Type* tinfo; + static TypeInfoDeclaration* create(Type* tinfo); + TypeInfoDeclaration* syntaxCopy(Dsymbol* s) final override; + const char* toChars() const final override; + TypeInfoDeclaration* isTypeInfoDeclaration() final override; void accept(Visitor* v) override; }; -class ModAssignExp final : public BinAssignExp +class TypeInfoStructDeclaration final : public TypeInfoDeclaration { public: + static TypeInfoStructDeclaration* create(Type* tinfo); void accept(Visitor* v) override; }; -class AndAssignExp final : public BinAssignExp +class TypeInfoClassDeclaration final : public TypeInfoDeclaration { public: + static TypeInfoClassDeclaration* create(Type* tinfo); void accept(Visitor* v) override; }; -class OrAssignExp final : public BinAssignExp +class TypeInfoInterfaceDeclaration final : public TypeInfoDeclaration { public: + static TypeInfoInterfaceDeclaration* create(Type* tinfo); void accept(Visitor* v) override; }; -class XorAssignExp final : public BinAssignExp +class TypeInfoPointerDeclaration final : public TypeInfoDeclaration { public: + static TypeInfoPointerDeclaration* create(Type* tinfo); void accept(Visitor* v) override; }; -class PowAssignExp final : public BinAssignExp +class TypeInfoArrayDeclaration final : public TypeInfoDeclaration { public: + static TypeInfoArrayDeclaration* create(Type* tinfo); void accept(Visitor* v) override; }; -class ShlAssignExp final : public BinAssignExp +class TypeInfoStaticArrayDeclaration final : public TypeInfoDeclaration { public: + static TypeInfoStaticArrayDeclaration* create(Type* tinfo); void accept(Visitor* v) override; }; -class ShrAssignExp final : public BinAssignExp +class TypeInfoAssociativeArrayDeclaration final : public TypeInfoDeclaration { public: + static TypeInfoAssociativeArrayDeclaration* create(Type* tinfo); void accept(Visitor* v) override; }; -class UshrAssignExp final : public BinAssignExp +class TypeInfoEnumDeclaration final : public TypeInfoDeclaration { public: + static TypeInfoEnumDeclaration* create(Type* tinfo); void accept(Visitor* v) override; }; -class CatAssignExp : public BinAssignExp +class TypeInfoFunctionDeclaration final : public TypeInfoDeclaration { public: - Expression* lowering; + static TypeInfoFunctionDeclaration* create(Type* tinfo); void accept(Visitor* v) override; }; -class CatElemAssignExp final : public CatAssignExp +class TypeInfoDelegateDeclaration final : public TypeInfoDeclaration { public: + static TypeInfoDelegateDeclaration* create(Type* tinfo); void accept(Visitor* v) override; }; -class CatDcharAssignExp final : public CatAssignExp +class TypeInfoTupleDeclaration final : public TypeInfoDeclaration { public: + static TypeInfoTupleDeclaration* create(Type* tinfo); void accept(Visitor* v) override; }; -class AddExp final : public BinExp +class TypeInfoConstDeclaration final : public TypeInfoDeclaration { public: + static TypeInfoConstDeclaration* create(Type* tinfo); void accept(Visitor* v) override; }; -class MinExp final : public BinExp +class TypeInfoInvariantDeclaration final : public TypeInfoDeclaration { public: + static TypeInfoInvariantDeclaration* create(Type* tinfo); void accept(Visitor* v) override; }; -class CatExp final : public BinExp +class TypeInfoSharedDeclaration final : public TypeInfoDeclaration { public: - Expression* lowering; + static TypeInfoSharedDeclaration* create(Type* tinfo); void accept(Visitor* v) override; }; -class MulExp final : public BinExp +class TypeInfoWildDeclaration final : public TypeInfoDeclaration { public: + static TypeInfoWildDeclaration* create(Type* tinfo); void accept(Visitor* v) override; }; -class DivExp final : public BinExp +class TypeInfoVectorDeclaration final : public TypeInfoDeclaration { public: + static TypeInfoVectorDeclaration* create(Type* tinfo); void accept(Visitor* v) override; }; -class ModExp final : public BinExp +class ThisDeclaration final : public VarDeclaration { public: + ThisDeclaration* syntaxCopy(Dsymbol* s) override; + ThisDeclaration* isThisDeclaration() override; void accept(Visitor* v) override; }; -class PowExp final : public BinExp +class EnumDeclaration final : public ScopeDsymbol { public: + Type* type; + Type* memtype; + Visibility visibility; + Expression* maxval; + Expression* minval; + Expression* defaultval; + bool isdeprecated() const; + bool isdeprecated(bool v); + bool added() const; + bool added(bool v); + bool inuse() const; + bool inuse(bool v); +private: + uint8_t bitFields; +public: + EnumDeclaration* syntaxCopy(Dsymbol* s) override; + bool oneMember(Dsymbol** ps, Identifier* ident) override; + Type* getType() override; + const char* kind() const override; + bool isDeprecated() const override; + Visibility visible() override; + bool isSpecial() const; + Expression* getDefaultValue(const Loc& loc); + Type* getMemtype(const Loc& loc); + EnumDeclaration* isEnumDeclaration() override; + Symbol* sinit; void accept(Visitor* v) override; }; -class ShlExp final : public BinExp +class EnumMember final : public VarDeclaration { public: + Expression*& value(); + Expression* origValue; + Type* origType; + EnumDeclaration* ed; + EnumMember* syntaxCopy(Dsymbol* s) override; + const char* kind() const override; + EnumMember* isEnumMember() override; void accept(Visitor* v) override; }; -class ShrExp final : public BinExp +class Import final : public Dsymbol { public: + _d_dynamicArray< Identifier* > packages; + Identifier* id; + Identifier* aliasId; + int32_t isstatic; + Visibility visibility; + Array names; + Array aliases; + Module* mod; + Package* pkg; + Array aliasdecls; + const char* kind() const override; + Visibility visible() override; + Import* syntaxCopy(Dsymbol* s) override; + Dsymbol* toAlias() override; + bool overloadInsert(Dsymbol* s) override; + Import* isImport() override; void accept(Visitor* v) override; }; -class UshrExp final : public BinExp +extern Expression* ctfeInterpret(Expression* e); + +extern void printCtfePerformanceStats(); + +extern const char* mangleExact(FuncDeclaration* fd); + +extern void mangleToBuffer(Type* t, OutBuffer& buf); + +extern void mangleToBuffer(Expression* e, OutBuffer& buf); + +extern void mangleToBuffer(Dsymbol* s, OutBuffer& buf); + +extern void mangleToBuffer(TemplateInstance* ti, OutBuffer& buf); + +class Package : public ScopeDsymbol { public: + PKG isPkgMod; + uint32_t tag; + Module* mod; + const char* kind() const override; + bool equals(const RootObject* const o) const override; + Package* isPackage() final override; + bool isAncestorPackageOf(const Package* const pkg) const; void accept(Visitor* v) override; + Module* isPackageMod(); + void resolvePKGunknown(); }; -class AndExp final : public BinExp +class Module final : public Package { public: + static Module* rootModule; + static DsymbolTable* modules; + static Array amodules; + static Array deferred; + static Array deferred2; + static Array deferred3; + static void _init(); + static void deinitialize(); + static AggregateDeclaration* moduleinfo; + _d_dynamicArray< const char > arg; + ModuleDeclaration* md; + const FileName srcfile; + const FileName objfile; + const FileName hdrfile; + FileName docfile; + _d_dynamicArray< const uint8_t > src; + uint32_t errors; + uint32_t numlines; + FileType filetype; + bool hasAlwaysInlines; + bool isPackageFile; + Package* pkg; + Array contentImportedFiles; + int32_t needmoduleinfo; +private: + ThreeState selfimports; + ThreeState rootimports; +public: + void* tagSymTab; +private: + OutBuffer defines; +public: + bool selfImports(); + bool rootImports(); + Identifier* searchCacheIdent; + Dsymbol* searchCacheSymbol; + uint32_t searchCacheFlags; + bool insearch; + Module* importedFrom; + Array* decldefs; + Array aimports; + uint32_t debuglevel; + Array* debugids; + Array* debugidsNot; + uint32_t versionlevel; + Array* versionids; + Array* versionidsNot; + MacroTable macrotable; + Escape* _escapetable; + size_t nameoffset; + size_t namelen; + static Module* create(const char* filename, Identifier* ident, int32_t doDocComment, int32_t doHdrGen); + static const char* find(const char* filename); + static Module* load(const Loc& loc, Array* packages, Identifier* ident); + const char* kind() const override; + bool read(const Loc& loc); + Module* parse(); + int32_t needModuleInfo(); + void checkImportDeprecation(const Loc& loc, Scope* sc); + bool isPackageAccessible(Package* p, Visibility visibility, uint32_t flags = 0u) override; + Dsymbol* symtabInsert(Dsymbol* s) override; + static void runDeferredSemantic(); + static void runDeferredSemantic2(); + static void runDeferredSemantic3(); + int32_t imports(Module* m); + bool isRoot(); + bool isCoreModule(Identifier* ident); + int32_t doppelganger; + Symbol* cov; + _d_dynamicArray< uint32_t > covb; + Symbol* sictor; + Symbol* sctor; + Symbol* sdtor; + Symbol* ssharedctor; + Symbol* sshareddtor; + Symbol* stest; + Symbol* sfilename; + void* ctfe_cov; + Module* isModule() override; void accept(Visitor* v) override; + void fullyQualifiedName(OutBuffer& buf); }; -class OrExp final : public BinExp +struct ModuleDeclaration final { -public: - void accept(Visitor* v) override; + Loc loc; + Identifier* id; + _d_dynamicArray< Identifier* > packages; + bool isdeprecated; + Expression* msg; + const char* toChars() const; + ModuleDeclaration() : + loc(), + id(), + packages(), + isdeprecated(), + msg() + { + } }; -class XorExp final : public BinExp +extern void getLocalClasses(Module* mod, Array& aclasses); + +extern FuncDeclaration* findGetMembers(ScopeDsymbol* dsym); + +extern void gendocfile(Module* m, const char* const ddoctext_ptr, size_t ddoctext_length, const char* const datetime, ErrorSink* eSink, OutBuffer& outbuf); + +struct Scope final { -public: - void accept(Visitor* v) override; + Scope* enclosing; + Module* _module; + ScopeDsymbol* scopesym; + FuncDeclaration* func; + VarDeclaration* varDecl; + Dsymbol* parent; + LabelStatement* slabel; + SwitchStatement* sw; + Statement* tryBody; + TryFinallyStatement* tf; + ScopeGuardStatement* os; + Statement* sbreak; + Statement* scontinue; + ForeachStatement* fes; + Scope* callsc; + Dsymbol* inunion; + bool nofree; + bool inLoop; + int32_t intypeof; + VarDeclaration* lastVar; + ErrorSink* eSink; + Module* minst; + TemplateInstance* tinst; + CtorFlow ctorflow; + AlignDeclaration* aligndecl; + CPPNamespaceDeclaration* namespace_; + LINK linkage; + CPPMANGLE cppmangle; + PragmaDeclaration* inlining; + Visibility visibility; + int32_t explicitVisibility; + StorageClass stc; + DeprecatedDeclaration* depdecl; + uint32_t flags; + UserAttributeDeclaration* userAttribDecl; + DocComment* lastdc; + void* anchorCounts; + Identifier* prevAnchor; + AliasDeclaration* aliasAsg; + Dsymbol* search(const Loc& loc, Identifier* ident, Dsymbol*& pscopesym, uint32_t flags = 0u); + Scope() : + enclosing(), + _module(), + scopesym(), + func(), + varDecl(), + parent(), + slabel(), + sw(), + tryBody(), + tf(), + os(), + sbreak(), + scontinue(), + fes(), + callsc(), + inunion(), + nofree(), + inLoop(), + intypeof(), + lastVar(), + eSink(), + minst(), + tinst(), + ctorflow(), + aligndecl(), + namespace_(), + linkage((LINK)1u), + cppmangle((CPPMANGLE)0u), + inlining(), + visibility(Visibility((Visibility::Kind)5u, nullptr)), + explicitVisibility(), + stc(), + depdecl(), + flags(), + userAttribDecl(), + lastdc(), + prevAnchor(), + aliasAsg() + { + } + Scope(Scope* enclosing, Module* _module = nullptr, ScopeDsymbol* scopesym = nullptr, FuncDeclaration* func = nullptr, VarDeclaration* varDecl = nullptr, Dsymbol* parent = nullptr, LabelStatement* slabel = nullptr, SwitchStatement* sw = nullptr, Statement* tryBody = nullptr, TryFinallyStatement* tf = nullptr, ScopeGuardStatement* os = nullptr, Statement* sbreak = nullptr, Statement* scontinue = nullptr, ForeachStatement* fes = nullptr, Scope* callsc = nullptr, Dsymbol* inunion = nullptr, bool nofree = false, bool inLoop = false, int32_t intypeof = 0, VarDeclaration* lastVar = nullptr, ErrorSink* eSink = nullptr, Module* minst = nullptr, TemplateInstance* tinst = nullptr, CtorFlow ctorflow = CtorFlow(), AlignDeclaration* aligndecl = nullptr, CPPNamespaceDeclaration* namespace_ = nullptr, LINK linkage = (LINK)1u, CPPMANGLE cppmangle = (CPPMANGLE)0u, PragmaDeclaration* inlining = nullptr, Visibility visibility = Visibility((Visibility::Kind)5u, nullptr), int32_t explicitVisibility = 0, uint64_t stc = 0LLU, DeprecatedDeclaration* depdecl = nullptr, uint32_t flags = 0u, UserAttributeDeclaration* userAttribDecl = nullptr, DocComment* lastdc = nullptr, void* anchorCounts = nullptr, Identifier* prevAnchor = nullptr, AliasDeclaration* aliasAsg = nullptr) : + enclosing(enclosing), + _module(_module), + scopesym(scopesym), + func(func), + varDecl(varDecl), + parent(parent), + slabel(slabel), + sw(sw), + tryBody(tryBody), + tf(tf), + os(os), + sbreak(sbreak), + scontinue(scontinue), + fes(fes), + callsc(callsc), + inunion(inunion), + nofree(nofree), + inLoop(inLoop), + intypeof(intypeof), + lastVar(lastVar), + eSink(eSink), + minst(minst), + tinst(tinst), + ctorflow(ctorflow), + aligndecl(aligndecl), + namespace_(namespace_), + linkage(linkage), + cppmangle(cppmangle), + inlining(inlining), + visibility(visibility), + explicitVisibility(explicitVisibility), + stc(stc), + depdecl(depdecl), + flags(flags), + userAttribDecl(userAttribDecl), + lastdc(lastdc), + anchorCounts(anchorCounts), + prevAnchor(prevAnchor), + aliasAsg(aliasAsg) + {} }; -class LogicalExp final : public BinExp -{ -public: - void accept(Visitor* v) override; -}; +extern FuncDeclaration* search_toString(StructDeclaration* sd); -class CmpExp final : public BinExp +class StructDeclaration : public AggregateDeclaration { public: - void accept(Visitor* v) override; -}; - -class InExp final : public BinExp -{ + Array postblits; + FuncDeclaration* postblit; + FuncDeclaration* xeq; + FuncDeclaration* xcmp; + FuncDeclaration* xhash; + static FuncDeclaration* xerreq; + static FuncDeclaration* xerrcmp; + TypeTuple* argTypes; + structalign_t alignment; + ThreeState ispod; + bool zeroInit() const; + bool zeroInit(bool v); + bool hasIdentityAssign() const; + bool hasIdentityAssign(bool v); + bool hasBlitAssign() const; + bool hasBlitAssign(bool v); + bool hasIdentityEquals() const; + bool hasIdentityEquals(bool v); + bool hasNoFields() const; + bool hasNoFields(bool v); + bool hasCopyCtor() const; + bool hasCopyCtor(bool v); + bool hasPointerField() const; + bool hasPointerField(bool v); + bool hasVoidInitPointers() const; + bool hasVoidInitPointers(bool v); + bool hasSystemFields() const; + bool hasSystemFields(bool v); + bool hasFieldWithInvariant() const; + bool hasFieldWithInvariant(bool v); + bool computedTypeProperties() const; + bool computedTypeProperties(bool v); + bool requestTypeInfo() const; + bool requestTypeInfo(bool v); +private: + uint16_t bitFields; public: + static StructDeclaration* create(const Loc& loc, Identifier* id, bool inObject); + StructDeclaration* syntaxCopy(Dsymbol* s) override; + const char* kind() const override; + void finalizeSize() final override; + bool isPOD(); + bool hasCopyConstruction(); + StructDeclaration* isStructDeclaration() final override; void accept(Visitor* v) override; + uint32_t numArgTypes() const; + Type* argType(uint32_t index); + bool hasRegularCtor(bool checkDisabled = false); }; -class RemoveExp final : public BinExp +class UnionDeclaration final : public StructDeclaration { public: + UnionDeclaration* syntaxCopy(Dsymbol* s) override; + const char* kind() const override; + UnionDeclaration* isUnionDeclaration() override; void accept(Visitor* v) override; }; -class EqualExp final : public BinExp +class WithScopeSymbol final : public ScopeDsymbol { public: + WithStatement* withstate; + WithScopeSymbol* isWithScopeSymbol() override; void accept(Visitor* v) override; }; -class IdentityExp final : public BinExp +class ArrayScopeSymbol final : public ScopeDsymbol { public: + RootObject* arrayContent; + ArrayScopeSymbol* isArrayScopeSymbol() override; void accept(Visitor* v) override; }; -class CondExp final : public BinExp +class OverloadSet final : public Dsymbol { public: - Expression* econd; - CondExp* syntaxCopy() override; - bool isLvalue() override; + Array a; + void push(Dsymbol* s); + OverloadSet* isOverloadSet() override; + const char* kind() const override; void accept(Visitor* v) override; }; -class DefaultInitExp : public Expression +class ForwardingScopeDsymbol final : public ScopeDsymbol { public: - void accept(Visitor* v) override; + Dsymbol* symtabInsert(Dsymbol* s) override; + Dsymbol* symtabLookup(Dsymbol* s, Identifier* id) override; + void importScope(Dsymbol* s, Visibility visibility) override; + const char* kind() const override; + ForwardingScopeDsymbol* isForwardingScopeDsymbol() override; }; -class FileInitExp final : public DefaultInitExp +class ExpressionDsymbol final : public Dsymbol { public: - void accept(Visitor* v) override; + Expression* exp; + ExpressionDsymbol(Expression* exp); + ExpressionDsymbol* isExpressionDsymbol() override; }; -class LineInitExp final : public DefaultInitExp +class AliasAssign final : public Dsymbol { public: + Identifier* ident; + Type* type; + Dsymbol* aliassym; + AliasAssign* syntaxCopy(Dsymbol* s) override; + AliasAssign* isAliasAssign() override; + const char* kind() const override; void accept(Visitor* v) override; }; -class ModuleInitExp final : public DefaultInitExp +class DsymbolTable final : public RootObject { public: - void accept(Visitor* v) override; + AssocArray tab; + Dsymbol* lookup(const Identifier* const ident); + void update(Dsymbol* s); + Dsymbol* insert(Dsymbol* s); + Dsymbol* insert(const Identifier* const ident, Dsymbol* s); + size_t length() const; + DsymbolTable(); }; -class FuncInitExp final : public DefaultInitExp -{ -public: - void accept(Visitor* v) override; -}; +extern void dsymbolSemantic(Dsymbol* dsym, Scope* sc); -class PrettyFuncInitExp final : public DefaultInitExp -{ -public: - void accept(Visitor* v) override; -}; +extern void addMember(Dsymbol* dsym, Scope* sc, ScopeDsymbol* sds); -class ClassReferenceExp final : public Expression -{ -public: - StructLiteralExp* value; - ClassDeclaration* originalClass(); - int32_t getFieldIndex(Type* fieldtype, uint32_t fieldoffset); - int32_t findFieldIndexByName(VarDeclaration* v); - void accept(Visitor* v) override; -}; +extern Dsymbol* search(Dsymbol* d, const Loc& loc, Identifier* ident, uint32_t flags = 0u); -class CTFEExp final : public Expression -{ -public: - const char* toChars() const override; -}; +extern void setScope(Dsymbol* d, Scope* sc); -class ThrownExceptionExp final : public Expression -{ -public: - ClassReferenceExp* thrown; - const char* toChars() const override; - void accept(Visitor* v) override; -}; +extern void importAll(Dsymbol* d, Scope* sc); -class ObjcClassReferenceExp final : public Expression +class ImportAllVisitor : public Visitor { public: - ClassDeclaration* classDeclaration; - void accept(Visitor* v) override; + using Visitor::visit; + Scope* sc; + ImportAllVisitor(Scope* sc); + void visit(Dsymbol* d) override; + void visit(Import* imp) override; + void visit(Module* m) override; + void visit(AttribDeclaration* atb) override; + void visit(StaticIfDeclaration* _) override; + void visit(StaticForeachDeclaration* _) override; }; -class GenericExp final : public Expression -{ -public: - Expression* cntlExp; - Array* types; - Array* exps; - GenericExp* syntaxCopy() override; - void accept(Visitor* v) override; -}; +extern void genCppHdrFiles(Array& ms); extern Expression* resolveProperties(Scope* sc, Expression* e); diff --git a/dmd/import.h b/dmd/import.h index 624cd7406a3..2a02f13ba55 100644 --- a/dmd/import.h +++ b/dmd/import.h @@ -41,7 +41,6 @@ class Import final : public Dsymbol const char *kind() const override; Visibility visible() override; Import *syntaxCopy(Dsymbol *s) override; // copy only syntax trees - void importAll(Scope *sc) override; Dsymbol *toAlias() override; bool overloadInsert(Dsymbol *s) override; diff --git a/dmd/module.h b/dmd/module.h index 8ebac76d6d3..80a6ea25965 100644 --- a/dmd/module.h +++ b/dmd/module.h @@ -121,7 +121,6 @@ class Module final : public Package const char *kind() const override; bool read(const Loc &loc); // read file, returns 'true' if succeed, 'false' otherwise. Module *parse(); // syntactic parse - void importAll(Scope *sc) override; int needModuleInfo(); bool isPackageAccessible(Package *p, Visibility visibility, SearchOptFlags flags = (SearchOptFlags)SearchOpt::all) override; Dsymbol *symtabInsert(Dsymbol *s) override; From fc0c94b019b0dee79d1284799aa3e16fa11f0d07 Mon Sep 17 00:00:00 2001 From: Walter Bright Date: Thu, 14 Dec 2023 02:09:06 -0800 Subject: [PATCH 098/215] fix Issue 23713 - compilable/testcstuff1.c:206:1: error: static assertion failed: sizeof(u'a') == 4 (dlang/dmd!15903) --- dmd/cparse.d | 12 ++++++++++++ dmd/lexer.d | 10 ++++++---- tests/dmd/compilable/testcstuff1.c | 3 ++- 3 files changed, 20 insertions(+), 5 deletions(-) diff --git a/dmd/cparse.d b/dmd/cparse.d index 6c55eee115c..4c0b96a4c8c 100644 --- a/dmd/cparse.d +++ b/dmd/cparse.d @@ -247,6 +247,8 @@ final class CParser(AST) : Parser!AST break; case TOK.charLiteral: + case TOK.wcharLiteral: + case TOK.dcharLiteral: case TOK.int32Literal: case TOK.uns32Literal: case TOK.int64Literal: @@ -725,6 +727,12 @@ final class CParser(AST) : Parser!AST nextToken(); break; + case TOK.wcharLiteral: + e = new AST.IntegerExp(loc, token.intvalue, AST.Type.tuns16); + nextToken(); + break; + + case TOK.dcharLiteral: case TOK.uns32Literal: e = new AST.IntegerExp(loc, token.unsvalue, AST.Type.tuns32); nextToken(); @@ -4946,6 +4954,8 @@ final class CParser(AST) : Parser!AST { case TOK.identifier: case TOK.charLiteral: + case TOK.wcharLiteral: + case TOK.dcharLiteral: case TOK.int32Literal: case TOK.uns32Literal: case TOK.int64Literal: @@ -5851,6 +5861,8 @@ final class CParser(AST) : Parser!AST case TOK.int32Literal: case TOK.charLiteral: t = AST.Type.tint32; goto Linteger; + case TOK.wcharLiteral: t = AST.Type.tuns16; goto Linteger; + case TOK.dcharLiteral: case TOK.uns32Literal: t = AST.Type.tuns32; goto Linteger; case TOK.int64Literal: t = AST.Type.tint64; goto Linteger; case TOK.uns64Literal: t = AST.Type.tuns64; goto Linteger; diff --git a/dmd/lexer.d b/dmd/lexer.d index af5a745afb2..2c6a5950569 100644 --- a/dmd/lexer.d +++ b/dmd/lexer.d @@ -2016,8 +2016,9 @@ class Lexer } if (d1 >= 0x1_0000) error(loc, "x%x does not fit in 16 bits", d1); - u = d1; - break; + t.unsvalue = d1; + t.value = TOK.wcharLiteral; // C11 6.4.4.4-9 + return; case 'U': dchar d; @@ -2028,8 +2029,9 @@ class Lexer else if (idx < n) error(loc, "max number of chars in 32 bit character literal is 1, had %d", cast(int)((n + 3) >> 2)); - u = d; - break; + t.unsvalue = d; + t.value = TOK.dcharLiteral; // C11 6.4.4.4-9 + return; default: assert(0); diff --git a/tests/dmd/compilable/testcstuff1.c b/tests/dmd/compilable/testcstuff1.c index 6d6028d0f84..d57ae9d81d9 100644 --- a/tests/dmd/compilable/testcstuff1.c +++ b/tests/dmd/compilable/testcstuff1.c @@ -210,7 +210,7 @@ __declspec(restrict) void* testrestrictdeclspec() // Character literals _Static_assert(sizeof('a') == 4, "ok"); -_Static_assert(sizeof(u'a') == 4, "ok"); +_Static_assert(sizeof(u'a') == 2, "ok"); _Static_assert(sizeof(U'a') == 4, "ok"); _Static_assert('a' == 0x61, "ok"); _Static_assert('ab' == 0x6162, "ok"); @@ -219,6 +219,7 @@ _Static_assert('abcd' == 0x61626364, "ok"); _Static_assert(u'a' == 0x61, "ok"); _Static_assert(u'ab' == 0x62, "ok"); _Static_assert(U'a' == 0x61, "ok"); +_Static_assert(U'a' - 500 > 0, "ok"); _Static_assert(u'\u1234' == 0x1234, "ok"); _Static_assert(L'\u1234' == 0x1234, "ok"); From aba2f4914debeb364f439e175a455981aa4fca55 Mon Sep 17 00:00:00 2001 From: Razvan Nitu Date: Thu, 14 Dec 2023 12:09:30 +0200 Subject: [PATCH 099/215] Delete useless imports in compiler/src/dmd/statement.d (dlang/dmd!15900) --- dmd/statement.d | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/dmd/statement.d b/dmd/statement.d index b5906c8edc3..f96ea0b7d83 100644 --- a/dmd/statement.d +++ b/dmd/statement.d @@ -26,13 +26,10 @@ import dmd.declaration; import dmd.dsymbol; import dmd.expression; import dmd.func; -import dmd.globals; -import dmd.hdrgen; import dmd.id; import dmd.identifier; import dmd.location; import dmd.mtype; -import dmd.common.outbuffer; import dmd.rootobject; import dmd.sapply; import dmd.staticassert; @@ -333,6 +330,8 @@ extern (C++) final class ErrorStatement : Statement extern (D) this() { super(Loc.initial, STMT.Error); + + import dmd.globals; assert(global.gaggedErrors || global.errors); } From a7e498eb9b97b15d08230ef1b1f688511149ff2e Mon Sep 17 00:00:00 2001 From: Razvan Nitu Date: Thu, 14 Dec 2023 13:48:39 +0200 Subject: [PATCH 100/215] Break dependency of compiler/src/dmd/statement.d on gluelayer (dlang/dmd!15901) --- dmd/frontend.h | 3 +-- dmd/statement.d | 3 +-- dmd/statement.h | 2 +- 3 files changed, 3 insertions(+), 5 deletions(-) diff --git a/dmd/frontend.h b/dmd/frontend.h index 3a81a867252..c1331c456a2 100644 --- a/dmd/frontend.h +++ b/dmd/frontend.h @@ -330,7 +330,6 @@ class InlineAsmStatement; class GccAsmStatement; class ImportStatement; struct Token; -struct code; class Object; class TypeInfo_Class; class TypeInfo; @@ -5744,7 +5743,7 @@ class ImportStatement final : public Statement class InlineAsmStatement final : public AsmStatement { public: - code* asmcode; + void* asmcode; uint32_t asmalign; uint32_t regs; bool refparam; diff --git a/dmd/statement.d b/dmd/statement.d index f96ea0b7d83..430454480e1 100644 --- a/dmd/statement.d +++ b/dmd/statement.d @@ -20,7 +20,6 @@ import dmd.arraytypes; import dmd.astenums; import dmd.ast_node; import dmd.errors; -import dmd.gluelayer; import dmd.cond; import dmd.declaration; import dmd.dsymbol; @@ -1772,7 +1771,7 @@ extern (C++) class AsmStatement : Statement */ extern (C++) final class InlineAsmStatement : AsmStatement { - code* asmcode; + void* asmcode; uint asmalign; // alignment of this statement uint regs; // mask of registers modified (must match regm_t in back end) bool refparam; // true if function parameter is referenced diff --git a/dmd/statement.h b/dmd/statement.h index ef8423f1cf7..1e493f0d188 100644 --- a/dmd/statement.h +++ b/dmd/statement.h @@ -716,7 +716,7 @@ class AsmStatement : public Statement class InlineAsmStatement final : public AsmStatement { public: - code *asmcode; + void *asmcode; unsigned asmalign; // alignment of this statement unsigned regs; // mask of registers modified (must match regm_t in back end) d_bool refparam; // true if function parameter is referenced From d3d1591761783989f413d0c452f8f4f3bd3eaeee Mon Sep 17 00:00:00 2001 From: RazvanN7 Date: Thu, 14 Dec 2023 15:05:51 +0200 Subject: [PATCH 101/215] Delete useless imports in compiler/src/dmd/staticassert.d --- dmd/staticassert.d | 3 --- 1 file changed, 3 deletions(-) diff --git a/dmd/staticassert.d b/dmd/staticassert.d index 7f22c4c993a..760c66a415a 100644 --- a/dmd/staticassert.d +++ b/dmd/staticassert.d @@ -14,14 +14,11 @@ module dmd.staticassert; import dmd.arraytypes; -import dmd.dscope; import dmd.dsymbol; import dmd.expression; -import dmd.globals; import dmd.location; import dmd.id; import dmd.identifier; -import dmd.mtype; import dmd.visitor; /*********************************************************** From e0c783379ad9add94413065d71c9383c932b2bc1 Mon Sep 17 00:00:00 2001 From: RazvanN7 Date: Thu, 14 Dec 2023 13:48:08 +0200 Subject: [PATCH 102/215] Extract dsymbol.setFieldOffset and move it into a visitor --- dmd/attrib.d | 80 --------- dmd/attrib.h | 2 - dmd/dclass.d | 2 +- dmd/declaration.d | 287 -------------------------------- dmd/declaration.h | 1 - dmd/dstruct.d | 2 +- dmd/dsymbol.d | 4 - dmd/dsymbol.h | 2 +- dmd/dsymbolsem.d | 408 ++++++++++++++++++++++++++++++++++++++++++++++ dmd/dtemplate.d | 9 - dmd/frontend.h | 10 +- dmd/nspace.d | 8 - dmd/nspace.h | 1 - dmd/template.h | 1 - 14 files changed, 413 insertions(+), 404 deletions(-) diff --git a/dmd/attrib.d b/dmd/attrib.d index b60fb73831b..cc6ef9c431b 100644 --- a/dmd/attrib.d +++ b/dmd/attrib.d @@ -143,11 +143,6 @@ extern (C++) abstract class AttribDeclaration : Dsymbol return Dsymbol.oneMembers(d, ps, ident); } - override void setFieldOffset(AggregateDeclaration ad, ref FieldState fieldState, bool isunion) - { - include(null).foreachDsymbol( s => s.setFieldOffset(ad, fieldState, isunion) ); - } - override final bool hasPointers() { return include(null).foreachDsymbol( (s) { return s.hasPointers(); } ) != 0; @@ -662,81 +657,6 @@ extern (C++) final class AnonDeclaration : AttribDeclaration return new AnonDeclaration(loc, isunion, Dsymbol.arraySyntaxCopy(decl)); } - override void setFieldOffset(AggregateDeclaration ad, ref FieldState fieldState, bool isunion) - { - //printf("\tAnonDeclaration::setFieldOffset %s %p\n", isunion ? "union" : "struct", this); - if (decl) - { - /* This works by treating an AnonDeclaration as an aggregate 'member', - * so in order to place that member we need to compute the member's - * size and alignment. - */ - size_t fieldstart = ad.fields.length; - - /* Hackishly hijack ad's structsize and alignsize fields - * for use in our fake anon aggregate member. - */ - uint savestructsize = ad.structsize; - uint savealignsize = ad.alignsize; - ad.structsize = 0; - ad.alignsize = 0; - - FieldState fs; - decl.foreachDsymbol( (s) - { - s.setFieldOffset(ad, fs, this.isunion); - if (this.isunion) - fs.offset = 0; - }); - - /* https://issues.dlang.org/show_bug.cgi?id=13613 - * If the fields in this.members had been already - * added in ad.fields, just update *poffset for the subsequent - * field offset calculation. - */ - if (fieldstart == ad.fields.length) - { - ad.structsize = savestructsize; - ad.alignsize = savealignsize; - fieldState.offset = ad.structsize; - return; - } - - anonstructsize = ad.structsize; - anonalignsize = ad.alignsize; - ad.structsize = savestructsize; - ad.alignsize = savealignsize; - - // 0 sized structs are set to 1 byte - if (anonstructsize == 0) - { - anonstructsize = 1; - anonalignsize = 1; - } - - assert(_scope); - auto alignment = _scope.alignment(); - - /* Given the anon 'member's size and alignment, - * go ahead and place it. - */ - anonoffset = placeField( - fieldState.offset, - anonstructsize, anonalignsize, alignment, - ad.structsize, ad.alignsize, - isunion); - - // Add to the anon fields the base offset of this anonymous aggregate - //printf("anon fields, anonoffset = %d\n", anonoffset); - foreach (const i; fieldstart .. ad.fields.length) - { - VarDeclaration v = ad.fields[i]; - //printf("\t[%d] %s %d\n", i, v.toChars(), v.offset); - v.offset += anonoffset; - } - } - } - override const(char)* kind() const { return (isunion ? "anonymous union" : "anonymous struct"); diff --git a/dmd/attrib.h b/dmd/attrib.h index b7092894471..35628e26105 100644 --- a/dmd/attrib.h +++ b/dmd/attrib.h @@ -29,7 +29,6 @@ class AttribDeclaration : public Dsymbol void addComment(const utf8_t *comment) override; const char *kind() const override; bool oneMember(Dsymbol **ps, Identifier *ident) override; - void setFieldOffset(AggregateDeclaration *ad, FieldState& fieldState, bool isunion) override; bool hasPointers() override final; bool hasStaticCtorOrDtor() override final; void checkCtorConstInit() override final; @@ -131,7 +130,6 @@ class AnonDeclaration final : public AttribDeclaration unsigned anonalignsize; // size of anonymous struct for alignment purposes AnonDeclaration *syntaxCopy(Dsymbol *s) override; - void setFieldOffset(AggregateDeclaration *ad, FieldState& fieldState, bool isunion) override; const char *kind() const override; AnonDeclaration *isAnonDeclaration() override { return this; } void accept(Visitor *v) override { v->visit(this); } diff --git a/dmd/dclass.d b/dmd/dclass.d index 187a4208729..9ff1b659e0a 100644 --- a/dmd/dclass.d +++ b/dmd/dclass.d @@ -594,7 +594,7 @@ extern (C++) class ClassDeclaration : AggregateDeclaration fieldState.offset = structsize; foreach (s; *members) { - s.setFieldOffset(this, fieldState, false); + s.setFieldOffset(this, &fieldState, false); } sizeok = Sizeok.done; diff --git a/dmd/declaration.d b/dmd/declaration.d index 0e125fdd001..bdc91f4f1f2 100644 --- a/dmd/declaration.d +++ b/dmd/declaration.d @@ -1214,88 +1214,6 @@ extern (C++) class VarDeclaration : Declaration return v; } - override void setFieldOffset(AggregateDeclaration ad, ref FieldState fieldState, bool isunion) - { - //printf("VarDeclaration::setFieldOffset(ad = %s) %s\n", ad.toChars(), toChars()); - - if (aliasTuple) - { - // If this variable was really a tuple, set the offsets for the tuple fields - aliasTuple.foreachVar((s) { s.setFieldOffset(ad, fieldState, isunion); }); - return; - } - - if (!isField()) - return; - assert(!(storage_class & (STC.static_ | STC.extern_ | STC.parameter))); - - //printf("+VarDeclaration::setFieldOffset(ad = %s) %s\n", ad.toChars(), toChars()); - - /* Fields that are tuples appear both as part of TupleDeclarations and - * as members. That means ignore them if they are already a field. - */ - if (offset) - { - // already a field - fieldState.offset = ad.structsize; // https://issues.dlang.org/show_bug.cgi?id=13613 - return; - } - for (size_t i = 0; i < ad.fields.length; i++) - { - if (ad.fields[i] == this) - { - // already a field - fieldState.offset = ad.structsize; // https://issues.dlang.org/show_bug.cgi?id=13613 - return; - } - } - - // Check for forward referenced types which will fail the size() call - Type t = type.toBasetype(); - if (storage_class & STC.ref_) - { - // References are the size of a pointer - t = Type.tvoidptr; - } - Type tv = t.baseElemOf(); - if (tv.ty == Tstruct) - { - auto ts = cast(TypeStruct)tv; - assert(ts.sym != ad); // already checked in ad.determineFields() - if (!ts.sym.determineSize(loc)) - { - type = Type.terror; - errors = true; - return; - } - } - - // List in ad.fields. Even if the type is error, it's necessary to avoid - // pointless error diagnostic "more initializers than fields" on struct literal. - ad.fields.push(this); - - if (t.ty == Terror) - return; - - /* If coming after a bit field in progress, - * advance past the field - */ - fieldState.inFlight = false; - - const sz = t.size(loc); - assert(sz != SIZE_INVALID && sz < uint.max); - uint memsize = cast(uint)sz; // size of member - uint memalignsize = target.fieldalign(t); // size of member for alignment purposes - offset = placeField( - fieldState.offset, - memsize, memalignsize, alignment, - ad.structsize, ad.alignsize, - isunion); - - //printf("\t%s: memalignsize = %d\n", toChars(), memalignsize); - //printf(" addField '%s' to '%s' at offset %d, size = %d\n", toChars(), ad.toChars(), offset, memsize); - } - override const(char)* kind() const { return "variable"; @@ -1803,211 +1721,6 @@ extern (C++) class BitFieldDeclaration : VarDeclaration : (1L << (width - 1)) - 1); return v; } - - override final void setFieldOffset(AggregateDeclaration ad, ref FieldState fieldState, bool isunion) - { - enum log = false; - static if (log) - { - printf("BitFieldDeclaration::setFieldOffset(ad: %s, field: %s)\n", ad.toChars(), toChars()); - void print(const ref FieldState fieldState) - { - fieldState.print(); - printf(" fieldWidth = %d bits\n", fieldWidth); - } - print(fieldState); - } - - Type t = type.toBasetype(); - const bool anon = isAnonymous(); - - // List in ad.fields. Even if the type is error, it's necessary to avoid - // pointless error diagnostic "more initializers than fields" on struct literal. - if (!anon) - ad.fields.push(this); - - if (t.ty == Terror) - return; - - const sz = t.size(loc); - assert(sz != SIZE_INVALID && sz < uint.max); - uint memsize = cast(uint)sz; // size of member - uint memalignsize = target.fieldalign(t); // size of member for alignment purposes - if (log) printf(" memsize: %u memalignsize: %u\n", memsize, memalignsize); - - if (fieldWidth == 0 && !anon) - error(loc, "named bit fields cannot have 0 width"); - if (fieldWidth > memsize * 8) - error(loc, "bit field width %d is larger than type", fieldWidth); - - const style = target.c.bitFieldStyle; - - void startNewField() - { - if (log) printf("startNewField()\n"); - uint alignsize; - if (style == TargetC.BitFieldStyle.Gcc_Clang) - { - if (fieldWidth > 32) - alignsize = memalignsize; - else if (fieldWidth > 16) - alignsize = 4; - else if (fieldWidth > 8) - alignsize = 2; - else - alignsize = 1; - } - else - alignsize = memsize; // not memalignsize - - uint dummy; - offset = placeField( - fieldState.offset, - memsize, alignsize, alignment, - ad.structsize, - (anon && style == TargetC.BitFieldStyle.Gcc_Clang) ? dummy : ad.alignsize, - isunion); - - fieldState.inFlight = true; - fieldState.fieldOffset = offset; - fieldState.bitOffset = 0; - fieldState.fieldSize = memsize; - } - - if (style == TargetC.BitFieldStyle.Gcc_Clang) - { - if (fieldWidth == 0) - { - if (!isunion) - { - // Use type of zero width field to align to next field - fieldState.offset = (fieldState.offset + memalignsize - 1) & ~(memalignsize - 1); - ad.structsize = fieldState.offset; - } - - fieldState.inFlight = false; - return; - } - - if (ad.alignsize == 0) - ad.alignsize = 1; - if (!anon && - ad.alignsize < memalignsize) - ad.alignsize = memalignsize; - } - else if (style == TargetC.BitFieldStyle.MS) - { - if (ad.alignsize == 0) - ad.alignsize = 1; - if (fieldWidth == 0) - { - if (fieldState.inFlight && !isunion) - { - // documentation says align to next int - //const alsz = cast(uint)Type.tint32.size(); - const alsz = memsize; // but it really does this - fieldState.offset = (fieldState.offset + alsz - 1) & ~(alsz - 1); - ad.structsize = fieldState.offset; - } - - fieldState.inFlight = false; - return; - } - } - else if (style == TargetC.BitFieldStyle.DM) - { - if (anon && fieldWidth && (!fieldState.inFlight || fieldState.bitOffset == 0)) - return; // this probably should be a bug in DMC - if (ad.alignsize == 0) - ad.alignsize = 1; - if (fieldWidth == 0) - { - if (fieldState.inFlight && !isunion) - { - const alsz = memsize; - fieldState.offset = (fieldState.offset + alsz - 1) & ~(alsz - 1); - ad.structsize = fieldState.offset; - } - - fieldState.inFlight = false; - return; - } - } - - if (!fieldState.inFlight) - { - //printf("not in flight\n"); - startNewField(); - } - else if (style == TargetC.BitFieldStyle.Gcc_Clang) - { - // If the bit-field spans more units of alignment than its type, - // start a new field at the next alignment boundary. - if (fieldState.bitOffset == fieldState.fieldSize * 8 && - fieldState.bitOffset + fieldWidth > memalignsize * 8) - { - if (log) printf("more units of alignment than its type\n"); - startNewField(); // the bit field is full - } - else - { - // if alignment boundary is crossed - uint start = fieldState.fieldOffset * 8 + fieldState.bitOffset; - uint end = start + fieldWidth; - //printf("%s start: %d end: %d memalignsize: %d\n", ad.toChars(), start, end, memalignsize); - if (start / (memalignsize * 8) != (end - 1) / (memalignsize * 8)) - { - if (log) printf("alignment is crossed\n"); - startNewField(); - } - } - } - else if (style == TargetC.BitFieldStyle.DM || - style == TargetC.BitFieldStyle.MS) - { - if (memsize != fieldState.fieldSize || - fieldState.bitOffset + fieldWidth > fieldState.fieldSize * 8) - { - //printf("new field\n"); - startNewField(); - } - } - else - assert(0); - - offset = fieldState.fieldOffset; - bitOffset = fieldState.bitOffset; - - const pastField = bitOffset + fieldWidth; - if (style == TargetC.BitFieldStyle.Gcc_Clang) - { - auto size = (pastField + 7) / 8; - fieldState.fieldSize = size; - //printf(" offset: %d, size: %d\n", offset, size); - if (isunion) - { - const newstructsize = offset + size; - if (newstructsize > ad.structsize) - ad.structsize = newstructsize; - } - else - ad.structsize = offset + size; - } - else - fieldState.fieldSize = memsize; - //printf("at end: ad.structsize = %d\n", cast(int)ad.structsize); - //print(fieldState); - - if (!isunion) - { - fieldState.offset = offset + fieldState.fieldSize; - fieldState.bitOffset = pastField; - } - - //printf("\t%s: offset = %d bitOffset = %d fieldWidth = %d memsize = %d\n", toChars(), offset, bitOffset, fieldWidth, memsize); - //printf("\t%s: memalignsize = %d\n", toChars(), memalignsize); - //printf(" addField '%s' to '%s' at offset %d, size = %d\n", toChars(), ad.toChars(), offset, memsize); - } } /*********************************************************** diff --git a/dmd/declaration.h b/dmd/declaration.h index a65fb4467e5..adbc26bf570 100644 --- a/dmd/declaration.h +++ b/dmd/declaration.h @@ -281,7 +281,6 @@ class VarDeclaration : public Declaration bool systemInferred(bool v); static VarDeclaration *create(const Loc &loc, Type *t, Identifier *id, Initializer *init, StorageClass storage_class = STCundefined); VarDeclaration *syntaxCopy(Dsymbol *) override; - void setFieldOffset(AggregateDeclaration *ad, FieldState& fieldState, bool isunion) override final; const char *kind() const override; AggregateDeclaration *isThis() override final; bool needThis() override final; diff --git a/dmd/dstruct.d b/dmd/dstruct.d index 36e847c3f88..0e0a1f52f88 100644 --- a/dmd/dstruct.d +++ b/dmd/dstruct.d @@ -289,7 +289,7 @@ extern (C++) class StructDeclaration : AggregateDeclaration for (size_t i = 0; i < members.length; i++) { Dsymbol s = (*members)[i]; - s.setFieldOffset(this, fieldState, isunion); + s.setFieldOffset(this, &fieldState, isunion); } if (type.ty == Terror) { diff --git a/dmd/dsymbol.d b/dmd/dsymbol.d index 05fcce5aa08..6613c2bc5c2 100644 --- a/dmd/dsymbol.d +++ b/dmd/dsymbol.d @@ -919,10 +919,6 @@ extern (C++) class Dsymbol : ASTNode return true; } - void setFieldOffset(AggregateDeclaration ad, ref FieldState fieldState, bool isunion) - { - } - /***************************************** * Is Dsymbol a variable that contains pointers? */ diff --git a/dmd/dsymbol.h b/dmd/dsymbol.h index b20d0aedbd3..d029c00fc1c 100644 --- a/dmd/dsymbol.h +++ b/dmd/dsymbol.h @@ -247,7 +247,6 @@ class Dsymbol : public ASTNode virtual Visibility visible(); virtual Dsymbol *syntaxCopy(Dsymbol *s); // copy only syntax trees virtual bool oneMember(Dsymbol **ps, Identifier *ident); - virtual void setFieldOffset(AggregateDeclaration *ad, FieldState& fieldState, bool isunion); virtual bool hasPointers(); virtual bool hasStaticCtorOrDtor(); virtual void addObjcSymbols(ClassDeclarations *, ClassDeclarations *) { } @@ -431,3 +430,4 @@ Dsymbol *search(Dsymbol *d, const Loc &loc, Identifier *ident, SearchOptFlags fl bool checkDeprecated(Dsymbol *d, const Loc &loc, Scope *sc); void setScope(Dsymbol *d, Scope *sc); void importAll(Dsymbol *d, Scope *sc); +void setFieldOffset(Dsymbol *d, AggregateDeclaration *ad, FieldState& fieldState, bool isunion); diff --git a/dmd/dsymbolsem.d b/dmd/dsymbolsem.d index ce4856c4f3b..828a33fd5fb 100644 --- a/dmd/dsymbolsem.d +++ b/dmd/dsymbolsem.d @@ -8888,3 +8888,411 @@ extern(C++) class ImportAllVisitor : Visitor // do not evaluate aggregate before semantic pass override void visit(StaticForeachDeclaration _) {} } + +extern(C++) void setFieldOffset(Dsymbol d, AggregateDeclaration ad, FieldState* fieldState, bool isunion) +{ + scope v = new SetFieldOffsetVisitor(ad, fieldState, isunion); + d.accept(v); +} + +private extern(C++) class SetFieldOffsetVisitor : Visitor +{ + alias visit = Visitor.visit; + + AggregateDeclaration ad; + FieldState* fieldState; + bool isunion; + + this(AggregateDeclaration ad, FieldState* fieldState, bool isunion) + { + this.ad = ad; + this.fieldState = fieldState; + this.isunion = isunion; + } + + override void visit(Dsymbol d) {} + + override void visit(Nspace ns) + { + //printf("Nspace::setFieldOffset() %s\n", toChars()); + if (ns._scope) // if fwd reference + dsymbolSemantic(ns, null); // try to resolve it + ns.members.foreachDsymbol( s => s.setFieldOffset(ad, fieldState, isunion) ); + } + + override void visit(VarDeclaration vd) + { + //printf("VarDeclaration::setFieldOffset(ad = %s) %s\n", ad.toChars(), vd.toChars()); + + if (vd.aliasTuple) + { + // If this variable was really a tuple, set the offsets for the tuple fields + vd.aliasTuple.foreachVar((s) { s.setFieldOffset(ad, fieldState, isunion); }); + return; + } + + if (!vd.isField()) + return; + assert(!(vd.storage_class & (STC.static_ | STC.extern_ | STC.parameter))); + + //printf("+VarDeclaration::setFieldOffset(ad = %s) %s\n", ad.toChars(), toChars()); + + /* Fields that are tuples appear both as part of TupleDeclarations and + * as members. That means ignore them if they are already a field. + */ + if (vd.offset) + { + // already a field + fieldState.offset = ad.structsize; // https://issues.dlang.org/show_bug.cgi?id=13613 + return; + } + for (size_t i = 0; i < ad.fields.length; i++) + { + if (ad.fields[i] == vd) + { + // already a field + fieldState.offset = ad.structsize; // https://issues.dlang.org/show_bug.cgi?id=13613 + return; + } + } + + // Check for forward referenced types which will fail the size() call + Type t = vd.type.toBasetype(); + if (vd.storage_class & STC.ref_) + { + // References are the size of a pointer + t = Type.tvoidptr; + } + Type tv = t.baseElemOf(); + if (tv.ty == Tstruct) + { + auto ts = cast(TypeStruct)tv; + assert(ts.sym != ad); // already checked in ad.determineFields() + if (!ts.sym.determineSize(vd.loc)) + { + vd.type = Type.terror; + vd.errors = true; + return; + } + } + + // List in ad.fields. Even if the type is error, it's necessary to avoid + // pointless error diagnostic "more initializers than fields" on struct literal. + ad.fields.push(vd); + + if (t.ty == Terror) + return; + + /* If coming after a bit field in progress, + * advance past the field + */ + fieldState.inFlight = false; + + const sz = t.size(vd.loc); + assert(sz != SIZE_INVALID && sz < uint.max); + uint memsize = cast(uint)sz; // size of member + uint memalignsize = target.fieldalign(t); // size of member for alignment purposes + vd.offset = placeField( + fieldState.offset, + memsize, memalignsize, vd.alignment, + ad.structsize, ad.alignsize, + isunion); + + //printf("\t%s: memalignsize = %d\n", toChars(), memalignsize); + //printf(" addField '%s' to '%s' at offset %d, size = %d\n", toChars(), ad.toChars(), offset, memsize); + } + + override void visit(BitFieldDeclaration bfd) + { + enum log = false; + static if (log) + { + printf("BitFieldDeclaration::setFieldOffset(ad: %s, field: %s)\n", ad.toChars(), bfd.toChars()); + void print(const FieldState* fieldState) + { + fieldState.print(); + printf(" fieldWidth = %d bits\n", bfd.fieldWidth); + } + print(fieldState); + } + + Type t = bfd.type.toBasetype(); + const bool anon = bfd.isAnonymous(); + + // List in ad.fields. Even if the type is error, it's necessary to avoid + // pointless error diagnostic "more initializers than fields" on struct literal. + if (!anon) + ad.fields.push(bfd); + + if (t.ty == Terror) + return; + + const sz = t.size(bfd.loc); + assert(sz != SIZE_INVALID && sz < uint.max); + uint memsize = cast(uint)sz; // size of member + uint memalignsize = target.fieldalign(t); // size of member for alignment purposes + if (log) printf(" memsize: %u memalignsize: %u\n", memsize, memalignsize); + + if (bfd.fieldWidth == 0 && !anon) + error(bfd.loc, "named bit fields cannot have 0 width"); + if (bfd.fieldWidth > memsize * 8) + error(bfd.loc, "bit field width %d is larger than type", bfd.fieldWidth); + + const style = target.c.bitFieldStyle; + + void startNewField() + { + if (log) printf("startNewField()\n"); + uint alignsize; + if (style == TargetC.BitFieldStyle.Gcc_Clang) + { + if (bfd.fieldWidth > 32) + alignsize = memalignsize; + else if (bfd.fieldWidth > 16) + alignsize = 4; + else if (bfd.fieldWidth > 8) + alignsize = 2; + else + alignsize = 1; + } + else + alignsize = memsize; // not memalignsize + + uint dummy; + bfd.offset = placeField( + fieldState.offset, + memsize, alignsize, bfd.alignment, + ad.structsize, + (anon && style == TargetC.BitFieldStyle.Gcc_Clang) ? dummy : ad.alignsize, + isunion); + + fieldState.inFlight = true; + fieldState.fieldOffset = bfd.offset; + fieldState.bitOffset = 0; + fieldState.fieldSize = memsize; + } + + if (style == TargetC.BitFieldStyle.Gcc_Clang) + { + if (bfd.fieldWidth == 0) + { + if (!isunion) + { + // Use type of zero width field to align to next field + fieldState.offset = (fieldState.offset + memalignsize - 1) & ~(memalignsize - 1); + ad.structsize = fieldState.offset; + } + + fieldState.inFlight = false; + return; + } + + if (ad.alignsize == 0) + ad.alignsize = 1; + if (!anon && + ad.alignsize < memalignsize) + ad.alignsize = memalignsize; + } + else if (style == TargetC.BitFieldStyle.MS) + { + if (ad.alignsize == 0) + ad.alignsize = 1; + if (bfd.fieldWidth == 0) + { + if (fieldState.inFlight && !isunion) + { + // documentation says align to next int + //const alsz = cast(uint)Type.tint32.size(); + const alsz = memsize; // but it really does this + fieldState.offset = (fieldState.offset + alsz - 1) & ~(alsz - 1); + ad.structsize = fieldState.offset; + } + + fieldState.inFlight = false; + return; + } + } + else if (style == TargetC.BitFieldStyle.DM) + { + if (anon && bfd.fieldWidth && (!fieldState.inFlight || fieldState.bitOffset == 0)) + return; // this probably should be a bug in DMC + if (ad.alignsize == 0) + ad.alignsize = 1; + if (bfd.fieldWidth == 0) + { + if (fieldState.inFlight && !isunion) + { + const alsz = memsize; + fieldState.offset = (fieldState.offset + alsz - 1) & ~(alsz - 1); + ad.structsize = fieldState.offset; + } + + fieldState.inFlight = false; + return; + } + } + + if (!fieldState.inFlight) + { + //printf("not in flight\n"); + startNewField(); + } + else if (style == TargetC.BitFieldStyle.Gcc_Clang) + { + // If the bit-field spans more units of alignment than its type, + // start a new field at the next alignment boundary. + if (fieldState.bitOffset == fieldState.fieldSize * 8 && + fieldState.bitOffset + bfd.fieldWidth > memalignsize * 8) + { + if (log) printf("more units of alignment than its type\n"); + startNewField(); // the bit field is full + } + else + { + // if alignment boundary is crossed + uint start = fieldState.fieldOffset * 8 + fieldState.bitOffset; + uint end = start + bfd.fieldWidth; + //printf("%s start: %d end: %d memalignsize: %d\n", ad.toChars(), start, end, memalignsize); + if (start / (memalignsize * 8) != (end - 1) / (memalignsize * 8)) + { + if (log) printf("alignment is crossed\n"); + startNewField(); + } + } + } + else if (style == TargetC.BitFieldStyle.DM || + style == TargetC.BitFieldStyle.MS) + { + if (memsize != fieldState.fieldSize || + fieldState.bitOffset + bfd.fieldWidth > fieldState.fieldSize * 8) + { + //printf("new field\n"); + startNewField(); + } + } + else + assert(0); + + bfd.offset = fieldState.fieldOffset; + bfd.bitOffset = fieldState.bitOffset; + + const pastField = bfd.bitOffset + bfd.fieldWidth; + if (style == TargetC.BitFieldStyle.Gcc_Clang) + { + auto size = (pastField + 7) / 8; + fieldState.fieldSize = size; + //printf(" offset: %d, size: %d\n", offset, size); + if (isunion) + { + const newstructsize = bfd.offset + size; + if (newstructsize > ad.structsize) + ad.structsize = newstructsize; + } + else + ad.structsize = bfd.offset + size; + } + else + fieldState.fieldSize = memsize; + //printf("at end: ad.structsize = %d\n", cast(int)ad.structsize); + //print(fieldState); + + if (!isunion) + { + fieldState.offset = bfd.offset + fieldState.fieldSize; + fieldState.bitOffset = pastField; + } + + //printf("\t%s: offset = %d bitOffset = %d fieldWidth = %d memsize = %d\n", toChars(), offset, bitOffset, fieldWidth, memsize); + //printf("\t%s: memalignsize = %d\n", toChars(), memalignsize); + //printf(" addField '%s' to '%s' at offset %d, size = %d\n", toChars(), ad.toChars(), offset, memsize); + } + + override void visit(TemplateMixin tm) + { + //printf("TemplateMixin.setFieldOffset() %s\n", tm.toChars()); + if (tm._scope) // if fwd reference + dsymbolSemantic(tm, null); // try to resolve it + + tm.members.foreachDsymbol( (s) { s.setFieldOffset(ad, fieldState, isunion); } ); + } + + override void visit(AttribDeclaration atd) + { + atd.include(null).foreachDsymbol( s => s.setFieldOffset(ad, fieldState, isunion) ); + } + + override void visit(AnonDeclaration anond) + { + //printf("\tAnonDeclaration::setFieldOffset %s %p\n", isunion ? "union" : "struct", anond); + if (anond.decl) + { + /* This works by treating an AnonDeclaration as an aggregate 'member', + * so in order to place that member we need to compute the member's + * size and alignment. + */ + size_t fieldstart = ad.fields.length; + + /* Hackishly hijack ad's structsize and alignsize fields + * for use in our fake anon aggregate member. + */ + uint savestructsize = ad.structsize; + uint savealignsize = ad.alignsize; + ad.structsize = 0; + ad.alignsize = 0; + + FieldState fs; + anond.decl.foreachDsymbol( (s) + { + s.setFieldOffset(ad, &fs, anond.isunion); + if (anond.isunion) + fs.offset = 0; + }); + + /* https://issues.dlang.org/show_bug.cgi?id=13613 + * If the fields in this.members had been already + * added in ad.fields, just update *poffset for the subsequent + * field offset calculation. + */ + if (fieldstart == ad.fields.length) + { + ad.structsize = savestructsize; + ad.alignsize = savealignsize; + fieldState.offset = ad.structsize; + return; + } + + anond.anonstructsize = ad.structsize; + anond.anonalignsize = ad.alignsize; + ad.structsize = savestructsize; + ad.alignsize = savealignsize; + + // 0 sized structs are set to 1 byte + if (anond.anonstructsize == 0) + { + anond.anonstructsize = 1; + anond.anonalignsize = 1; + } + + assert(anond._scope); + auto alignment = anond._scope.alignment(); + + /* Given the anon 'member's size and alignment, + * go ahead and place it. + */ + anond.anonoffset = placeField( + fieldState.offset, + anond.anonstructsize, anond.anonalignsize, alignment, + ad.structsize, ad.alignsize, + isunion); + + // Add to the anon fields the base offset of this anonymous aggregate + //printf("anon fields, anonoffset = %d\n", anonoffset); + foreach (const i; fieldstart .. ad.fields.length) + { + VarDeclaration v = ad.fields[i]; + //printf("\t[%d] %s %d\n", i, v.toChars(), v.offset); + v.offset += anond.anonoffset; + } + } + } +} diff --git a/dmd/dtemplate.d b/dmd/dtemplate.d index 360628ce3c2..e440b9e2eb6 100644 --- a/dmd/dtemplate.d +++ b/dmd/dtemplate.d @@ -7831,15 +7831,6 @@ extern (C++) final class TemplateMixin : TemplateInstance return members.foreachDsymbol( (s) { return s.hasPointers(); } ) != 0; } - override void setFieldOffset(AggregateDeclaration ad, ref FieldState fieldState, bool isunion) - { - //printf("TemplateMixin.setFieldOffset() %s\n", toChars()); - if (_scope) // if fwd reference - dsymbolSemantic(this, null); // try to resolve it - - members.foreachDsymbol( (s) { s.setFieldOffset(ad, fieldState, isunion); } ); - } - override const(char)* toChars() const { OutBuffer buf; diff --git a/dmd/frontend.h b/dmd/frontend.h index c1331c456a2..e25ce140067 100644 --- a/dmd/frontend.h +++ b/dmd/frontend.h @@ -52,7 +52,6 @@ class LabelDsymbol; class ClassDeclaration; class Type; class Package; -struct FieldState; template struct Array; class UnitTestDeclaration; @@ -515,7 +514,6 @@ class Dsymbol : public ASTNode virtual Visibility visible(); virtual Dsymbol* syntaxCopy(Dsymbol* s); virtual bool oneMember(Dsymbol** ps, Identifier* ident); - virtual void setFieldOffset(AggregateDeclaration* ad, FieldState& fieldState, bool isunion); virtual bool hasPointers(); virtual bool hasStaticCtorOrDtor(); virtual void addObjcSymbols(Array* classes, Array* categories); @@ -1535,7 +1533,6 @@ class TemplateMixin final : public TemplateInstance const char* kind() const override; bool oneMember(Dsymbol** ps, Identifier* ident) override; bool hasPointers() override; - void setFieldOffset(AggregateDeclaration* ad, FieldState& fieldState, bool isunion) override; const char* toChars() const override; TemplateMixin* isTemplateMixin() override; void accept(Visitor* v) override; @@ -5348,7 +5345,6 @@ class Nspace final : public ScopeDsymbol Expression* identExp; Nspace* syntaxCopy(Dsymbol* s) override; bool hasPointers() override; - void setFieldOffset(AggregateDeclaration* ad, FieldState& fieldState, bool isunion) override; const char* kind() const override; Nspace* isNspace() override; void accept(Visitor* v) override; @@ -6797,7 +6793,6 @@ class AttribDeclaration : public Dsymbol void addComment(const char* comment) override; const char* kind() const override; bool oneMember(Dsymbol** ps, Identifier* ident) override; - void setFieldOffset(AggregateDeclaration* ad, FieldState& fieldState, bool isunion) override; bool hasPointers() final override; bool hasStaticCtorOrDtor() final override; void checkCtorConstInit() final override; @@ -6891,7 +6886,6 @@ class AnonDeclaration final : public AttribDeclaration uint32_t anonstructsize; uint32_t anonalignsize; AnonDeclaration* syntaxCopy(Dsymbol* s) override; - void setFieldOffset(AggregateDeclaration* ad, FieldState& fieldState, bool isunion) override; const char* kind() const override; AnonDeclaration* isAnonDeclaration() override; void accept(Visitor* v) override; @@ -7333,7 +7327,6 @@ class VarDeclaration : public Declaration uint8_t isdataseg; static VarDeclaration* create(const Loc& loc, Type* type, Identifier* ident, Initializer* _init, StorageClass storage_class = static_cast(STC::undefined_)); VarDeclaration* syntaxCopy(Dsymbol* s) override; - void setFieldOffset(AggregateDeclaration* ad, FieldState& fieldState, bool isunion) override; const char* kind() const override; AggregateDeclaration* isThis() final override; bool needThis() final override; @@ -7363,7 +7356,6 @@ class BitFieldDeclaration : public VarDeclaration BitFieldDeclaration* isBitFieldDeclaration() final override; void accept(Visitor* v) override; uint64_t getMinMax(Identifier* id); - void setFieldOffset(AggregateDeclaration* ad, FieldState& fieldState, bool isunion) final override; }; class SymbolDeclaration final : public Declaration @@ -7993,6 +7985,8 @@ class ImportAllVisitor : public Visitor void visit(StaticForeachDeclaration* _) override; }; +extern void setFieldOffset(Dsymbol* d, AggregateDeclaration* ad, FieldState* fieldState, bool isunion); + extern void genCppHdrFiles(Array& ms); extern Expression* resolveProperties(Scope* sc, Expression* e); diff --git a/dmd/nspace.d b/dmd/nspace.d index 22c6e63a465..4607d3c41ad 100644 --- a/dmd/nspace.d +++ b/dmd/nspace.d @@ -91,14 +91,6 @@ extern (C++) final class Nspace : ScopeDsymbol return members.foreachDsymbol( (s) { return s.hasPointers(); } ) != 0; } - override void setFieldOffset(AggregateDeclaration ad, ref FieldState fieldState, bool isunion) - { - //printf("Nspace::setFieldOffset() %s\n", toChars()); - if (_scope) // if fwd reference - dsymbolSemantic(this, null); // try to resolve it - members.foreachDsymbol( s => s.setFieldOffset(ad, fieldState, isunion) ); - } - override const(char)* kind() const { return "namespace"; diff --git a/dmd/nspace.h b/dmd/nspace.h index 701cc935eb5..4a1bd9141ec 100644 --- a/dmd/nspace.h +++ b/dmd/nspace.h @@ -22,7 +22,6 @@ class Nspace final : public ScopeDsymbol Expression *identExp; Nspace *syntaxCopy(Dsymbol *s) override; bool hasPointers() override; - void setFieldOffset(AggregateDeclaration *ad, FieldState& fieldState, bool isunion) override; const char *kind() const override; Nspace *isNspace() override { return this; } void accept(Visitor *v) override { v->visit(this); } diff --git a/dmd/template.h b/dmd/template.h index 44f95ec0ec3..4be136102c2 100644 --- a/dmd/template.h +++ b/dmd/template.h @@ -311,7 +311,6 @@ class TemplateMixin final : public TemplateInstance const char *kind() const override; bool oneMember(Dsymbol **ps, Identifier *ident) override; bool hasPointers() override; - void setFieldOffset(AggregateDeclaration *ad, FieldState& fieldState, bool isunion) override; const char *toChars() const override; TemplateMixin *isTemplateMixin() override { return this; } From e1b56657e030802821cf822330ca59267dcb14a9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=A1=D0=B5=D0=BC=D1=91=D0=BD=20=D0=9C=D0=B0=D1=80=D1=8C?= =?UTF-8?q?=D1=8F=D1=81=D0=B8=D0=BD?= Date: Fri, 15 Dec 2023 12:02:20 +0300 Subject: [PATCH 103/215] Fix a bug on MacOS with app subprocess hanging on fork() (dlang/dmd!15606) I could not yet create a minimal reproducing example for this issue. I have a dylib written in D. This dylib is dynamically loaded (with `dlopen`) from a program written in Go. After I load the dylib and call its initializer method (which, among other things, calls `Runtime.initialize()`), and then try to run any subprocess from the main app, it hangs forever. In that state it has 2 identically looking processes: the main one waits for the child, and the child is hanging with 100% CPU load in the `MOV` instruction from this line: https://github.com/dlang/dmd/blob/355e5661790f1b7574d0311f40f5acc9f212d6f2/druntime/src/core/thread/osthread.d#L1954 Looks like it happens because we try to write to some "strange" memory area. I'll yet try to implement a minimal reproducing sample. --- runtime/druntime/src/core/thread/osthread.d | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/runtime/druntime/src/core/thread/osthread.d b/runtime/druntime/src/core/thread/osthread.d index 54af6ce0fc8..eaa128f3fe7 100644 --- a/runtime/druntime/src/core/thread/osthread.d +++ b/runtime/druntime/src/core/thread/osthread.d @@ -1951,6 +1951,13 @@ extern (C) void thread_init() @nogc nothrow static extern(C) void initChildAfterFork() { auto thisThread = Thread.getThis(); + if (!thisThread) + { + // It is possible that runtime was not properly initialized in the current process or thread - + // it may happen after `fork` call when using a dynamically loaded shared library written in D from a multithreaded non-D program. + // In such case getThis will return null. + return; + } thisThread.m_addr = pthread_self(); assert( thisThread.m_addr != thisThread.m_addr.init ); thisThread.m_tmach = pthread_mach_thread_np( thisThread.m_addr ); From 87fdccdf7fadafe9df891ea5de6011fea9c58677 Mon Sep 17 00:00:00 2001 From: RazvanN7 Date: Tue, 7 Nov 2023 14:13:50 +0200 Subject: [PATCH 104/215] Break dependency of expression.d on gluelayer.d --- dmd/expression.d | 3 +-- dmd/expression.h | 2 +- dmd/frontend.h | 2 +- 3 files changed, 3 insertions(+), 4 deletions(-) diff --git a/dmd/expression.d b/dmd/expression.d index cd93e54932c..f51a8b00891 100644 --- a/dmd/expression.d +++ b/dmd/expression.d @@ -21,7 +21,6 @@ import dmd.aggregate; import dmd.arraytypes; import dmd.astenums; import dmd.ast_node; -import dmd.gluelayer; import dmd.dclass; import dmd.declaration; import dmd.dimport; @@ -2240,7 +2239,7 @@ extern (C++) final class StructLiteralExp : Expression // while `sym` is only used in `e2ir/s2ir/tocsym` which comes after union { - Symbol* sym; /// back end symbol to initialize with literal + void* sym; /// back end symbol to initialize with literal (used as a Symbol*) /// those fields need to prevent a infinite recursion when one field of struct initialized with 'this' pointer. StructLiteralExp inlinecopy; diff --git a/dmd/expression.h b/dmd/expression.h index b4ace74b496..464094c4126 100644 --- a/dmd/expression.h +++ b/dmd/expression.h @@ -434,7 +434,7 @@ class StructLiteralExp final : public Expression union { - Symbol *sym; // back end symbol to initialize with literal + void *sym; // back end symbol to initialize with literal (used as a Symbol*) // those fields need to prevent a infinite recursion when one field of struct initialized with 'this' pointer. StructLiteralExp *inlinecopy; diff --git a/dmd/frontend.h b/dmd/frontend.h index e25ce140067..bbf843cdfc9 100644 --- a/dmd/frontend.h +++ b/dmd/frontend.h @@ -3384,7 +3384,7 @@ class StructLiteralExp final : public Expression Type* stype; union { - Symbol* sym; + void* sym; StructLiteralExp* inlinecopy; }; StructLiteralExp* origin; From bebd074613b7a3393182b86bac4207fafaad14a2 Mon Sep 17 00:00:00 2001 From: RazvanN7 Date: Fri, 15 Dec 2023 11:17:12 +0200 Subject: [PATCH 105/215] Delete useless imports in compiler/src/dmd/nspace.d --- dmd/nspace.d | 8 -------- 1 file changed, 8 deletions(-) diff --git a/dmd/nspace.d b/dmd/nspace.d index 4607d3c41ad..65f7d2964cb 100644 --- a/dmd/nspace.d +++ b/dmd/nspace.d @@ -46,22 +46,14 @@ module dmd.nspace; -import dmd.aggregate; import dmd.arraytypes; -import dmd.astenums; -import dmd.dscope; import dmd.dsymbol; -import dmd.dsymbolsem; -import dmd.errors; import dmd.expression; -import dmd.globals; import dmd.identifier; import dmd.location; import dmd.visitor; import core.stdc.stdio; -private enum LOG = false; - /// Ditto extern (C++) final class Nspace : ScopeDsymbol { From f8438c8b812e1807ca22f5d43e8904b7104fe215 Mon Sep 17 00:00:00 2001 From: RazvanN7 Date: Fri, 15 Dec 2023 12:31:27 +0200 Subject: [PATCH 106/215] Move dmd.mtype.Type.covariant to dmd.typesem --- dmd/ctfeexpr.d | 3 + dmd/dclass.d | 1 + dmd/frontend.h | 17 +- dmd/func.d | 4 + dmd/mtype.d | 259 +-------------------------- dmd/mtype.h | 2 +- dmd/typesem.d | 257 ++++++++++++++++++++++++++ tests/dmd/unit/semantic/covariance.d | 1 + 8 files changed, 276 insertions(+), 268 deletions(-) diff --git a/dmd/ctfeexpr.d b/dmd/ctfeexpr.d index 43efc05b5d3..993bab023f9 100644 --- a/dmd/ctfeexpr.d +++ b/dmd/ctfeexpr.d @@ -636,8 +636,11 @@ bool isSafePointerCast(Type srcPointee, Type destPointee) // It's OK if function pointers differ only in safe/pure/nothrow if (srcPointee.ty == Tfunction && destPointee.ty == Tfunction) + { + import dmd.typesem : covariant; return srcPointee.covariant(destPointee) == Covariant.yes || destPointee.covariant(srcPointee) == Covariant.yes; + } // it's OK to cast to void* if (destPointee.ty == Tvoid) return true; diff --git a/dmd/dclass.d b/dmd/dclass.d index 9ff1b659e0a..e066d877e8a 100644 --- a/dmd/dclass.d +++ b/dmd/dclass.d @@ -670,6 +670,7 @@ extern (C++) class ClassDeclaration : AggregateDeclaration void searchVtbl(ref Dsymbols vtbl) { + import dmd.typesem : covariant; bool seenInterfaceVirtual; foreach (s; vtbl) { diff --git a/dmd/frontend.h b/dmd/frontend.h index bbf843cdfc9..24ea90ef05b 100644 --- a/dmd/frontend.h +++ b/dmd/frontend.h @@ -1689,14 +1689,6 @@ enum class TY : uint8_t Ttag = 47u, }; -enum class Covariant -{ - distinct = 0, - yes = 1, - no = 2, - fwdref = 3, -}; - typedef uint64_t dinteger_t; class Type : public ASTNode @@ -1807,7 +1799,6 @@ class Type : public ASTNode bool equivalent(Type* t); DYNCAST dyncast() const final override; size_t getUniqueID() const; - Covariant covariant(Type* t, uint64_t* pstc = nullptr, bool cppCovariant = false); const char* toChars() const final override; char* toPrettyChars(bool QualifyTypes = false); static void _init(); @@ -4205,6 +4196,14 @@ extern Initializer* initializerSemantic(Initializer* init, Scope* sc, Type*& tx, extern Expression* initializerToExpression(Initializer* init, Type* itype = nullptr, const bool isCfile = false); +enum class Covariant +{ + distinct = 0, + yes = 1, + no = 2, + fwdref = 3, +}; + enum class DotExpFlag { none = 0, diff --git a/dmd/func.d b/dmd/func.d index 351faa471f2..d082928b068 100644 --- a/dmd/func.d +++ b/dmd/func.d @@ -695,6 +695,7 @@ extern (C++) class FuncDeclaration : Declaration int result = 0; if (fd.ident == ident) { + import dmd.typesem : covariant; const cov = type.covariant(fd.type); if (cov != Covariant.distinct) { @@ -721,6 +722,8 @@ extern (C++) class FuncDeclaration : Declaration final int findVtblIndex(Dsymbols* vtbl, int dim) { //printf("findVtblIndex() %s\n", toChars()); + import dmd.typesem : covariant; + FuncDeclaration mismatch = null; StorageClass mismatchstc = 0; int mismatchvi = -1; @@ -947,6 +950,7 @@ extern (C++) class FuncDeclaration : Declaration */ if (t.ty == Tfunction) { + import dmd.typesem : covariant; auto tf = cast(TypeFunction)f.type; if (tf.covariant(t) == Covariant.yes && tf.nextOf().implicitConvTo(t.nextOf()) >= MATCH.constant) diff --git a/dmd/mtype.d b/dmd/mtype.d index 9b96bf50dc7..a65326b3ce2 100644 --- a/dmd/mtype.d +++ b/dmd/mtype.d @@ -19,7 +19,6 @@ import core.stdc.string; import dmd.aggregate; import dmd.arraytypes; -import dmd.attrib; import dmd.astenums; import dmd.ast_node; import dmd.gluelayer; @@ -522,262 +521,6 @@ extern (C++) abstract class Type : ASTNode return mcache; } - /******************************* - * Covariant means that 'this' can substitute for 't', - * i.e. a pure function is a match for an impure type. - * Params: - * t = type 'this' is covariant with - * pstc = if not null, store STCxxxx which would make it covariant - * cppCovariant = true if extern(C++) function types should follow C++ covariant rules - * Returns: - * An enum value of either `Covariant.yes` or a reason it's not covariant. - */ - final Covariant covariant(Type t, StorageClass* pstc = null, bool cppCovariant = false) - { - version (none) - { - printf("Type::covariant(t = %s) %s\n", t.toChars(), toChars()); - printf("deco = %p, %p\n", deco, t.deco); - // printf("ty = %d\n", next.ty); - printf("mod = %x, %x\n", mod, t.mod); - } - if (pstc) - *pstc = 0; - StorageClass stc = 0; - - bool notcovariant = false; - - if (equals(t)) - return Covariant.yes; - - TypeFunction t1 = this.isTypeFunction(); - TypeFunction t2 = t.isTypeFunction(); - - if (!t1 || !t2) - goto Ldistinct; - - if (t1.parameterList.varargs != t2.parameterList.varargs) - goto Ldistinct; - - if (t1.parameterList.parameters && t2.parameterList.parameters) - { - if (t1.parameterList.length != t2.parameterList.length) - goto Ldistinct; - - foreach (i, fparam1; t1.parameterList) - { - Parameter fparam2 = t2.parameterList[i]; - Type tp1 = fparam1.type; - Type tp2 = fparam2.type; - - if (!tp1.equals(tp2)) - { - if (tp1.ty == tp2.ty) - { - if (auto tc1 = tp1.isTypeClass()) - { - if (tc1.sym == (cast(TypeClass)tp2).sym && MODimplicitConv(tp2.mod, tp1.mod)) - goto Lcov; - } - else if (auto ts1 = tp1.isTypeStruct()) - { - if (ts1.sym == (cast(TypeStruct)tp2).sym && MODimplicitConv(tp2.mod, tp1.mod)) - goto Lcov; - } - else if (tp1.ty == Tpointer) - { - if (tp2.implicitConvTo(tp1)) - goto Lcov; - } - else if (tp1.ty == Tarray) - { - if (tp2.implicitConvTo(tp1)) - goto Lcov; - } - else if (tp1.ty == Tdelegate) - { - if (tp2.implicitConvTo(tp1)) - goto Lcov; - } - } - goto Ldistinct; - } - Lcov: - notcovariant |= !fparam1.isCovariant(t1.isref, fparam2); - - /* https://issues.dlang.org/show_bug.cgi?id=23135 - * extern(C++) mutable parameters are not covariant with const. - */ - if (t1.linkage == LINK.cpp && cppCovariant) - { - notcovariant |= tp1.isNaked() != tp2.isNaked(); - if (auto tpn1 = tp1.nextOf()) - notcovariant |= tpn1.isNaked() != tp2.nextOf().isNaked(); - } - } - } - else if (t1.parameterList.parameters != t2.parameterList.parameters) - { - if (t1.parameterList.length || t2.parameterList.length) - goto Ldistinct; - } - - // The argument lists match - if (notcovariant) - goto Lnotcovariant; - if (t1.linkage != t2.linkage) - goto Lnotcovariant; - - { - // Return types - Type t1n = t1.next; - Type t2n = t2.next; - - if (!t1n || !t2n) // happens with return type inference - goto Lnotcovariant; - - if (t1n.equals(t2n)) - goto Lcovariant; - if (t1n.ty == Tclass && t2n.ty == Tclass) - { - /* If same class type, but t2n is const, then it's - * covariant. Do this test first because it can work on - * forward references. - */ - if ((cast(TypeClass)t1n).sym == (cast(TypeClass)t2n).sym && MODimplicitConv(t1n.mod, t2n.mod)) - goto Lcovariant; - - // If t1n is forward referenced: - ClassDeclaration cd = (cast(TypeClass)t1n).sym; - if (cd.semanticRun < PASS.semanticdone && !cd.isBaseInfoComplete()) - cd.dsymbolSemantic(null); - if (!cd.isBaseInfoComplete()) - { - return Covariant.fwdref; - } - } - if (t1n.ty == Tstruct && t2n.ty == Tstruct) - { - if ((cast(TypeStruct)t1n).sym == (cast(TypeStruct)t2n).sym && MODimplicitConv(t1n.mod, t2n.mod)) - goto Lcovariant; - } - else if (t1n.ty == t2n.ty && t1n.implicitConvTo(t2n)) - { - if (t1.isref && t2.isref) - { - // Treat like pointers to t1n and t2n - if (t1n.constConv(t2n) < MATCH.constant) - goto Lnotcovariant; - } - goto Lcovariant; - } - else if (t1n.ty == Tnull) - { - // NULL is covariant with any pointer type, but not with any - // dynamic arrays, associative arrays or delegates. - // https://issues.dlang.org/show_bug.cgi?id=8589 - // https://issues.dlang.org/show_bug.cgi?id=19618 - Type t2bn = t2n.toBasetype(); - if (t2bn.ty == Tnull || t2bn.ty == Tpointer || t2bn.ty == Tclass) - goto Lcovariant; - } - // bottom type is covariant to any type - else if (t1n.ty == Tnoreturn) - goto Lcovariant; - } - goto Lnotcovariant; - - Lcovariant: - if (t1.isref != t2.isref) - goto Lnotcovariant; - - if (!t1.isref && (t1.isScopeQual || t2.isScopeQual)) - { - StorageClass stc1 = t1.isScopeQual ? STC.scope_ : 0; - StorageClass stc2 = t2.isScopeQual ? STC.scope_ : 0; - if (t1.isreturn) - { - stc1 |= STC.return_; - if (!t1.isScopeQual) - stc1 |= STC.ref_; - } - if (t2.isreturn) - { - stc2 |= STC.return_; - if (!t2.isScopeQual) - stc2 |= STC.ref_; - } - if (!Parameter.isCovariantScope(t1.isref, stc1, stc2)) - goto Lnotcovariant; - } - - // We can subtract 'return ref' from 'this', but cannot add it - else if (t1.isreturn && !t2.isreturn) - goto Lnotcovariant; - - /* https://issues.dlang.org/show_bug.cgi?id=23135 - * extern(C++) mutable member functions are not covariant with const. - */ - if (t1.linkage == LINK.cpp && cppCovariant && t1.isNaked() != t2.isNaked()) - goto Lnotcovariant; - - /* Can convert mutable to const - */ - if (!MODimplicitConv(t2.mod, t1.mod)) - { - version (none) - { - //stop attribute inference with const - // If adding 'const' will make it covariant - if (MODimplicitConv(t2.mod, MODmerge(t1.mod, MODFlags.const_))) - stc |= STC.const_; - else - goto Lnotcovariant; - } - else - { - goto Ldistinct; - } - } - - /* Can convert pure to impure, nothrow to throw, and nogc to gc - */ - if (!t1.purity && t2.purity) - stc |= STC.pure_; - - if (!t1.isnothrow && t2.isnothrow) - stc |= STC.nothrow_; - - if (!t1.isnogc && t2.isnogc) - stc |= STC.nogc; - - /* Can convert safe/trusted to system - */ - if (t1.trust <= TRUST.system && t2.trust >= TRUST.trusted) - { - // Should we infer trusted or safe? Go with safe. - stc |= STC.safe; - } - - if (stc) - { - if (pstc) - *pstc = stc; - goto Lnotcovariant; - } - - //printf("\tcovaraint: 1\n"); - return Covariant.yes; - - Ldistinct: - //printf("\tcovaraint: 0\n"); - return Covariant.distinct; - - Lnotcovariant: - //printf("\tcovaraint: 2\n"); - return Covariant.no; - } - /******************************** * For pretty-printing a type. */ @@ -6935,7 +6678,7 @@ extern (C++) final class Parameter : ASTNode return isCovariantScope(returnByRef, thisSTC, otherSTC); } - extern (D) private static bool isCovariantScope(bool returnByRef, StorageClass from, StorageClass to) pure nothrow @nogc @safe + extern (D) static bool isCovariantScope(bool returnByRef, StorageClass from, StorageClass to) pure nothrow @nogc @safe { // Workaround for failing covariance when finding a common type of delegates, // some of which have parameters with inferred scope diff --git a/dmd/mtype.h b/dmd/mtype.h index 675e944050b..06afdbd32ec 100644 --- a/dmd/mtype.h +++ b/dmd/mtype.h @@ -225,7 +225,6 @@ class Type : public ASTNode // kludge for template.isType() DYNCAST dyncast() const override final { return DYNCAST_TYPE; } size_t getUniqueID() const; - Covariant covariant(Type *, StorageClass * = NULL, bool = false); const char *toChars() const override; char *toPrettyChars(bool QualifyTypes = false); static void _init(); @@ -929,3 +928,4 @@ class TypeTag final : public Type // If the type is a class or struct, returns the symbol for it, else null. AggregateDeclaration *isAggregate(Type *t); +Covariant covariant(Type *, Type *, StorageClass * = NULL, bool = false); diff --git a/dmd/typesem.d b/dmd/typesem.d index 46500764686..eec9e9f3360 100644 --- a/dmd/typesem.d +++ b/dmd/typesem.d @@ -4748,6 +4748,263 @@ Type getComplexLibraryType(const ref Loc loc, Scope* sc, TY ty) return *pt; } +/******************************* + * Covariant means that 'src' can substitute for 't', + * i.e. a pure function is a match for an impure type. + * Params: + * src = source type + * t = type 'src' is covariant with + * pstc = if not null, store STCxxxx which would make it covariant + * cppCovariant = true if extern(C++) function types should follow C++ covariant rules + * Returns: + * An enum value of either `Covariant.yes` or a reason it's not covariant. + */ +Covariant covariant(Type src, Type t, StorageClass* pstc = null, bool cppCovariant = false) +{ + version (none) + { + printf("Type::covariant(t = %s) %s\n", t.toChars(), src.toChars()); + printf("deco = %p, %p\n", src.deco, t.deco); + // printf("ty = %d\n", next.ty); + printf("mod = %x, %x\n", src.mod, t.mod); + } + if (pstc) + *pstc = 0; + StorageClass stc = 0; + + bool notcovariant = false; + + if (src.equals(t)) + return Covariant.yes; + + TypeFunction t1 = src.isTypeFunction(); + TypeFunction t2 = t.isTypeFunction(); + + if (!t1 || !t2) + goto Ldistinct; + + if (t1.parameterList.varargs != t2.parameterList.varargs) + goto Ldistinct; + + if (t1.parameterList.parameters && t2.parameterList.parameters) + { + if (t1.parameterList.length != t2.parameterList.length) + goto Ldistinct; + + foreach (i, fparam1; t1.parameterList) + { + Parameter fparam2 = t2.parameterList[i]; + Type tp1 = fparam1.type; + Type tp2 = fparam2.type; + + if (!tp1.equals(tp2)) + { + if (tp1.ty == tp2.ty) + { + if (auto tc1 = tp1.isTypeClass()) + { + if (tc1.sym == (cast(TypeClass)tp2).sym && MODimplicitConv(tp2.mod, tp1.mod)) + goto Lcov; + } + else if (auto ts1 = tp1.isTypeStruct()) + { + if (ts1.sym == (cast(TypeStruct)tp2).sym && MODimplicitConv(tp2.mod, tp1.mod)) + goto Lcov; + } + else if (tp1.ty == Tpointer) + { + if (tp2.implicitConvTo(tp1)) + goto Lcov; + } + else if (tp1.ty == Tarray) + { + if (tp2.implicitConvTo(tp1)) + goto Lcov; + } + else if (tp1.ty == Tdelegate) + { + if (tp2.implicitConvTo(tp1)) + goto Lcov; + } + } + goto Ldistinct; + } + Lcov: + notcovariant |= !fparam1.isCovariant(t1.isref, fparam2); + + /* https://issues.dlang.org/show_bug.cgi?id=23135 + * extern(C++) mutable parameters are not covariant with const. + */ + if (t1.linkage == LINK.cpp && cppCovariant) + { + notcovariant |= tp1.isNaked() != tp2.isNaked(); + if (auto tpn1 = tp1.nextOf()) + notcovariant |= tpn1.isNaked() != tp2.nextOf().isNaked(); + } + } + } + else if (t1.parameterList.parameters != t2.parameterList.parameters) + { + if (t1.parameterList.length || t2.parameterList.length) + goto Ldistinct; + } + + // The argument lists match + if (notcovariant) + goto Lnotcovariant; + if (t1.linkage != t2.linkage) + goto Lnotcovariant; + + { + // Return types + Type t1n = t1.next; + Type t2n = t2.next; + + if (!t1n || !t2n) // happens with return type inference + goto Lnotcovariant; + + if (t1n.equals(t2n)) + goto Lcovariant; + if (t1n.ty == Tclass && t2n.ty == Tclass) + { + /* If same class type, but t2n is const, then it's + * covariant. Do this test first because it can work on + * forward references. + */ + if ((cast(TypeClass)t1n).sym == (cast(TypeClass)t2n).sym && MODimplicitConv(t1n.mod, t2n.mod)) + goto Lcovariant; + + // If t1n is forward referenced: + ClassDeclaration cd = (cast(TypeClass)t1n).sym; + if (cd.semanticRun < PASS.semanticdone && !cd.isBaseInfoComplete()) + cd.dsymbolSemantic(null); + if (!cd.isBaseInfoComplete()) + { + return Covariant.fwdref; + } + } + if (t1n.ty == Tstruct && t2n.ty == Tstruct) + { + if ((cast(TypeStruct)t1n).sym == (cast(TypeStruct)t2n).sym && MODimplicitConv(t1n.mod, t2n.mod)) + goto Lcovariant; + } + else if (t1n.ty == t2n.ty && t1n.implicitConvTo(t2n)) + { + if (t1.isref && t2.isref) + { + // Treat like pointers to t1n and t2n + if (t1n.constConv(t2n) < MATCH.constant) + goto Lnotcovariant; + } + goto Lcovariant; + } + else if (t1n.ty == Tnull) + { + // NULL is covariant with any pointer type, but not with any + // dynamic arrays, associative arrays or delegates. + // https://issues.dlang.org/show_bug.cgi?id=8589 + // https://issues.dlang.org/show_bug.cgi?id=19618 + Type t2bn = t2n.toBasetype(); + if (t2bn.ty == Tnull || t2bn.ty == Tpointer || t2bn.ty == Tclass) + goto Lcovariant; + } + // bottom type is covariant to any type + else if (t1n.ty == Tnoreturn) + goto Lcovariant; + } + goto Lnotcovariant; + +Lcovariant: + if (t1.isref != t2.isref) + goto Lnotcovariant; + + if (!t1.isref && (t1.isScopeQual || t2.isScopeQual)) + { + StorageClass stc1 = t1.isScopeQual ? STC.scope_ : 0; + StorageClass stc2 = t2.isScopeQual ? STC.scope_ : 0; + if (t1.isreturn) + { + stc1 |= STC.return_; + if (!t1.isScopeQual) + stc1 |= STC.ref_; + } + if (t2.isreturn) + { + stc2 |= STC.return_; + if (!t2.isScopeQual) + stc2 |= STC.ref_; + } + if (!Parameter.isCovariantScope(t1.isref, stc1, stc2)) + goto Lnotcovariant; + } + + // We can subtract 'return ref' from 'this', but cannot add it + else if (t1.isreturn && !t2.isreturn) + goto Lnotcovariant; + + /* https://issues.dlang.org/show_bug.cgi?id=23135 + * extern(C++) mutable member functions are not covariant with const. + */ + if (t1.linkage == LINK.cpp && cppCovariant && t1.isNaked() != t2.isNaked()) + goto Lnotcovariant; + + /* Can convert mutable to const + */ + if (!MODimplicitConv(t2.mod, t1.mod)) + { + version (none) + { + //stop attribute inference with const + // If adding 'const' will make it covariant + if (MODimplicitConv(t2.mod, MODmerge(t1.mod, MODFlags.const_))) + stc |= STC.const_; + else + goto Lnotcovariant; + } + else + { + goto Ldistinct; + } + } + + /* Can convert pure to impure, nothrow to throw, and nogc to gc + */ + if (!t1.purity && t2.purity) + stc |= STC.pure_; + + if (!t1.isnothrow && t2.isnothrow) + stc |= STC.nothrow_; + + if (!t1.isnogc && t2.isnogc) + stc |= STC.nogc; + + /* Can convert safe/trusted to system + */ + if (t1.trust <= TRUST.system && t2.trust >= TRUST.trusted) + { + // Should we infer trusted or safe? Go with safe. + stc |= STC.safe; + } + + if (stc) + { + if (pstc) + *pstc = stc; + goto Lnotcovariant; + } + + //printf("\tcovaraint: 1\n"); + return Covariant.yes; + +Ldistinct: + //printf("\tcovaraint: 0\n"); + return Covariant.distinct; + +Lnotcovariant: + //printf("\tcovaraint: 2\n"); + return Covariant.no; +} + /******************************* Private *****************************************/ private: diff --git a/tests/dmd/unit/semantic/covariance.d b/tests/dmd/unit/semantic/covariance.d index e68742cd22c..dc2123146d9 100644 --- a/tests/dmd/unit/semantic/covariance.d +++ b/tests/dmd/unit/semantic/covariance.d @@ -7,6 +7,7 @@ module semantic.covariance; import dmd.astenums : STC, StorageClass; import dmd.func : FuncDeclaration; import dmd.mtype : Covariant, Type; +import dmd.typesem : covariant; import support; From f537ee484f84c95a5e6eb7836441088e6f1744b9 Mon Sep 17 00:00:00 2001 From: RazvanN7 Date: Fri, 15 Dec 2023 13:03:29 +0200 Subject: [PATCH 107/215] Move dmd.type.checkDeprecated to dmd/dsymbolsem.d and make it private --- dmd/dsymbolsem.d | 14 ++++++++++++++ dmd/frontend.h | 2 -- dmd/mtype.d | 18 ------------------ dmd/mtype.h | 2 -- 4 files changed, 14 insertions(+), 22 deletions(-) diff --git a/dmd/dsymbolsem.d b/dmd/dsymbolsem.d index 828a33fd5fb..df0a9a536f4 100644 --- a/dmd/dsymbolsem.d +++ b/dmd/dsymbolsem.d @@ -246,6 +246,20 @@ bool checkDeprecated(Dsymbol d, const ref Loc loc, Scope* sc) return true; } +/********************************* + * Check type to see if it is based on a deprecated symbol. + */ +private void checkDeprecated(Type type, const ref Loc loc, Scope* sc) +{ + if (Dsymbol s = type.toDsymbol(sc)) + { + s.checkDeprecated(loc, sc); + } + + if (auto tn = type.nextOf()) + tn.checkDeprecated(loc, sc); +} + // Returns true if a contract can appear without a function body. package bool allowsContractWithoutBody(FuncDeclaration funcdecl) { diff --git a/dmd/frontend.h b/dmd/frontend.h index 24ea90ef05b..ea33176c0ad 100644 --- a/dmd/frontend.h +++ b/dmd/frontend.h @@ -1821,7 +1821,6 @@ class Type : public ASTNode virtual bool isString(); virtual bool isAssignable(); virtual bool isBoolean(); - virtual void checkDeprecated(const Loc& loc, Scope* sc); bool isConst() const; bool isImmutable() const; bool isMutable() const; @@ -4803,7 +4802,6 @@ class TypeNext : public Type { public: Type* next; - void checkDeprecated(const Loc& loc, Scope* sc) final override; int32_t hasWild() const final override; Type* nextOf() final override; Type* makeConst() final override; diff --git a/dmd/mtype.d b/dmd/mtype.d index a65326b3ce2..1f55ef232fa 100644 --- a/dmd/mtype.d +++ b/dmd/mtype.d @@ -804,17 +804,6 @@ extern (C++) abstract class Type : ASTNode return isscalar(); } - /********************************* - * Check type to see if it is based on a deprecated symbol. - */ - void checkDeprecated(const ref Loc loc, Scope* sc) - { - if (Dsymbol s = toDsymbol(sc)) - { - s.checkDeprecated(loc, sc); - } - } - final bool isConst() const nothrow pure @nogc @safe { return (mod & MODFlags.const_) != 0; @@ -2568,13 +2557,6 @@ extern (C++) abstract class TypeNext : Type this.next = next; } - override final void checkDeprecated(const ref Loc loc, Scope* sc) - { - Type.checkDeprecated(loc, sc); - if (next) // next can be NULL if TypeFunction and auto return type - next.checkDeprecated(loc, sc); - } - override final int hasWild() const { if (ty == Tfunction) diff --git a/dmd/mtype.h b/dmd/mtype.h index 06afdbd32ec..ef1ce100640 100644 --- a/dmd/mtype.h +++ b/dmd/mtype.h @@ -248,7 +248,6 @@ class Type : public ASTNode virtual bool isString(); virtual bool isAssignable(); virtual bool isBoolean(); - virtual void checkDeprecated(const Loc &loc, Scope *sc); bool isConst() const { return (mod & MODconst) != 0; } bool isImmutable() const { return (mod & MODimmutable) != 0; } bool isMutable() const { return (mod & (MODconst | MODimmutable | MODwild)) == 0; } @@ -363,7 +362,6 @@ class TypeNext : public Type public: Type *next; - void checkDeprecated(const Loc &loc, Scope *sc) override final; int hasWild() const override final; Type *nextOf() override final; Type *makeConst() override final; From 667940b0a649bcf91c754f4e6bff953dd54a3243 Mon Sep 17 00:00:00 2001 From: RazvanN7 Date: Fri, 15 Dec 2023 13:48:36 +0200 Subject: [PATCH 108/215] Break dependency of dmd/mtype.d on dmd/expressionsem.d --- dmd/func.d | 1 + dmd/mtype.d | 524 +------------------------------------------------- dmd/typesem.d | 523 +++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 525 insertions(+), 523 deletions(-) diff --git a/dmd/func.d b/dmd/func.d index d082928b068..feaa5bb4d91 100644 --- a/dmd/func.d +++ b/dmd/func.d @@ -1161,6 +1161,7 @@ extern (C++) class FuncDeclaration : Declaration args.push(e); } + import dmd.typesem : callMatch; MATCH m = tg.callMatch(null, ArgumentList(&args, names), 1); if (m > MATCH.nomatch) { diff --git a/dmd/mtype.d b/dmd/mtype.d index 1f55ef232fa..626bf7431f0 100644 --- a/dmd/mtype.d +++ b/dmd/mtype.d @@ -34,7 +34,6 @@ import dmd.dsymbolsem; import dmd.dtemplate; import dmd.errors; import dmd.expression; -import dmd.expressionsem; import dmd.func; import dmd.globals; import dmd.hdrgen; @@ -4337,27 +4336,7 @@ extern (C++) final class TypeFunction : TypeNext return t.merge(); } - // arguments get specially formatted - private const(char)* getParamError(Expression arg, Parameter par) - { - if (global.gag && !global.params.v.showGaggedErrors) - return null; - // show qualification when toChars() is the same but types are different - // https://issues.dlang.org/show_bug.cgi?id=19948 - // when comparing the type with strcmp, we need to drop the qualifier - bool qual = !arg.type.mutableOf().equals(par.type.mutableOf()) && - strcmp(arg.type.mutableOf().toChars(), par.type.mutableOf().toChars()) == 0; - auto at = qual ? arg.type.toPrettyChars(true) : arg.type.toChars(); - OutBuffer buf; - // only mention rvalue if it's relevant - const rv = !arg.isLvalue() && par.isReference(); - buf.printf("cannot pass %sargument `%s` of type `%s` to parameter `%s`", - rv ? "rvalue ".ptr : "".ptr, arg.toChars(), at, - parameterToChars(par, this, qual)); - return buf.extractChars(); - } - - private extern(D) const(char)* getMatchError(A...)(const(char)* format, A args) + extern(D) static const(char)* getMatchError(A...)(const(char)* format, A args) { if (global.gag && !global.params.v.showGaggedErrors) return null; @@ -4366,185 +4345,6 @@ extern (C++) final class TypeFunction : TypeNext return buf.extractChars(); } - /******************************** - * 'args' are being matched to function 'this' - * Determine match level. - * Params: - * tthis = type of `this` pointer, null if not member function - * argumentList = arguments to function call - * flag = 1: performing a partial ordering match - * pMessage = address to store error message, or null - * sc = context - * Returns: - * MATCHxxxx - */ - extern (D) MATCH callMatch(Type tthis, ArgumentList argumentList, int flag = 0, const(char)** pMessage = null, Scope* sc = null) - { - //printf("TypeFunction::callMatch() %s\n", toChars()); - MATCH match = MATCH.exact; // assume exact match - ubyte wildmatch = 0; - - if (tthis) - { - Type t = tthis; - if (t.toBasetype().ty == Tpointer) - t = t.toBasetype().nextOf(); // change struct* to struct - if (t.mod != mod) - { - if (MODimplicitConv(t.mod, mod)) - match = MATCH.constant; - else if ((mod & MODFlags.wild) && MODimplicitConv(t.mod, (mod & ~MODFlags.wild) | MODFlags.const_)) - { - match = MATCH.constant; - } - else - return MATCH.nomatch; - } - if (isWild()) - { - if (t.isWild()) - wildmatch |= MODFlags.wild; - else if (t.isConst()) - wildmatch |= MODFlags.const_; - else if (t.isImmutable()) - wildmatch |= MODFlags.immutable_; - else - wildmatch |= MODFlags.mutable; - } - } - - const nparams = parameterList.length; - if (argumentList.length > nparams) - { - if (parameterList.varargs == VarArg.none) - { - // suppress early exit if an error message is wanted, - // so we can check any matching args are valid - if (!pMessage) - return MATCH.nomatch; - } - // too many args; no match - match = MATCH.convert; // match ... with a "conversion" match level - } - - // https://issues.dlang.org/show_bug.cgi?id=22997 - if (parameterList.varargs == VarArg.none && nparams > argumentList.length && !parameterList.hasDefaultArgs) - { - OutBuffer buf; - buf.printf("too few arguments, expected %d, got %d", cast(int)nparams, cast(int)argumentList.length); - if (pMessage) - *pMessage = buf.extractChars(); - return MATCH.nomatch; - } - auto resolvedArgs = resolveNamedArgs(argumentList, pMessage); - Expression[] args; - if (!resolvedArgs) - { - if (!pMessage || *pMessage) - return MATCH.nomatch; - - // if no message was provided, it was because of overflow which will be diagnosed below - match = MATCH.nomatch; - args = argumentList.arguments ? (*argumentList.arguments)[] : null; - } - else - { - args = (*resolvedArgs)[]; - } - - foreach (u, p; parameterList) - { - if (u >= args.length) - break; - - Expression arg = args[u]; - if (!arg) - continue; // default argument - - Type tprm = p.type; - Type targ = arg.type; - - if (!(p.isLazy() && tprm.ty == Tvoid && targ.ty != Tvoid)) - { - const isRef = p.isReference(); - wildmatch |= targ.deduceWild(tprm, isRef); - } - } - if (wildmatch) - { - /* Calculate wild matching modifier - */ - if (wildmatch & MODFlags.const_ || wildmatch & (wildmatch - 1)) - wildmatch = MODFlags.const_; - else if (wildmatch & MODFlags.immutable_) - wildmatch = MODFlags.immutable_; - else if (wildmatch & MODFlags.wild) - wildmatch = MODFlags.wild; - else - { - assert(wildmatch & MODFlags.mutable); - wildmatch = MODFlags.mutable; - } - } - - foreach (u, p; parameterList) - { - MATCH m; - - assert(p); - - // One or more arguments remain - if (u < args.length) - { - Expression arg = args[u]; - if (!arg) - continue; // default argument - m = argumentMatchParameter(this, p, arg, wildmatch, flag, sc, pMessage); - } - else if (p.defaultArg) - continue; - - /* prefer matching the element type rather than the array - * type when more arguments are present with T[]... - */ - if (parameterList.varargs == VarArg.typesafe && u + 1 == nparams && args.length > nparams) - goto L1; - - //printf("\tm = %d\n", m); - if (m == MATCH.nomatch) // if no match - { - L1: - if (parameterList.varargs == VarArg.typesafe && u + 1 == nparams) // if last varargs param - { - auto trailingArgs = args[u .. $]; - if (auto vmatch = matchTypeSafeVarArgs(this, p, trailingArgs, pMessage)) - return vmatch < match ? vmatch : match; - // Error message was already generated in `matchTypeSafeVarArgs` - return MATCH.nomatch; - } - if (pMessage && u >= args.length) - *pMessage = getMatchError("missing argument for parameter #%d: `%s`", - u + 1, parameterToChars(p, this, false)); - // If an error happened previously, `pMessage` was already filled - else if (pMessage && !*pMessage) - *pMessage = getParamError(args[u], p); - - return MATCH.nomatch; - } - if (m < match) - match = m; // pick worst match - } - - if (pMessage && !parameterList.varargs && args.length > nparams) - { - // all parameters had a match, but there are surplus args - *pMessage = getMatchError("expected %d argument(s), not %d", nparams, args.length); - return MATCH.nomatch; - } - //printf("match = %d\n", match); - return match; - } - /******************************** * Convert an `argumentList`, which may contain named arguments, into * a list of arguments in the order of the parameter list. @@ -6959,328 +6759,6 @@ const(char)* toChars(ScopeRef sr) pure nothrow @nogc @safe } } -/** - * Used by `callMatch` to check if the copy constructor may be called to - * copy the argument - * - * This is done by seeing if a call to the copy constructor can be made: - * ``` - * typeof(tprm) __copytmp; - * copytmp.__copyCtor(arg); - * ``` - */ -private extern(D) bool isCopyConstructorCallable (StructDeclaration argStruct, - Expression arg, Type tprm, Scope* sc, const(char)** pMessage) -{ - auto tmp = new VarDeclaration(arg.loc, tprm, Identifier.generateId("__copytmp"), null); - tmp.storage_class = STC.rvalue | STC.temp | STC.ctfe; - tmp.dsymbolSemantic(sc); - Expression ve = new VarExp(arg.loc, tmp); - Expression e = new DotIdExp(arg.loc, ve, Id.ctor); - e = new CallExp(arg.loc, e, arg); - //printf("e = %s\n", e.toChars()); - if (.trySemantic(e, sc)) - return true; - - if (pMessage) - { - /* https://issues.dlang.org/show_bug.cgi?id=22202 - * - * If a function was deduced by semantic on the CallExp, - * it means that resolveFuncCall completed succesfully. - * Therefore, there exists a callable copy constructor, - * however, it cannot be called because scope constraints - * such as purity, safety or nogc. - */ - OutBuffer buf; - auto callExp = e.isCallExp(); - if (auto f = callExp.f) - { - char[] s; - if (!f.isPure && sc.func.setImpure()) - s ~= "pure "; - if (!f.isSafe() && !f.isTrusted() && sc.setUnsafe()) - s ~= "@safe "; - if (!f.isNogc && sc.func.setGC(arg.loc, null)) - s ~= "nogc "; - if (s) - { - s[$-1] = '\0'; - buf.printf("`%s` copy constructor cannot be called from a `%s` context", f.type.toChars(), s.ptr); - } - else if (f.isGenerated() && f.isDisabled()) - { - /* https://issues.dlang.org/show_bug.cgi?id=23097 - * Compiler generated copy constructor failed. - */ - buf.printf("generating a copy constructor for `struct %s` failed, therefore instances of it are uncopyable", - argStruct.toChars()); - } - else - { - /* Although a copy constructor may exist, no suitable match was found. - * i.e: `inout` constructor creates `const` object, not mutable. - * Fallback to using the original generic error before https://issues.dlang.org/show_bug.cgi?id=22202. - */ - goto Lnocpctor; - } - } - else - { - Lnocpctor: - buf.printf("`struct %s` does not define a copy constructor for `%s` to `%s` copies", - argStruct.toChars(), arg.type.toChars(), tprm.toChars()); - } - - *pMessage = buf.extractChars(); - } - return false; -} - -/** - * Match a single parameter to an argument. - * - * This function is called by `TypeFunction.callMatch` while iterating over - * the list of parameter. Here we check if `arg` is a match for `p`, - * which is mostly about checking if `arg.type` converts to `p`'s type - * and some check about value reference. - * - * Params: - * tf = The `TypeFunction`, only used for error reporting - * p = The parameter of `tf` being matched - * arg = Argument being passed (bound) to `p` - * wildmatch = Wild (`inout`) matching level, derived from the full argument list - * flag = A non-zero value means we're doing a partial ordering check - * (no value semantic check) - * sc = Scope we are in - * pMessage = A buffer to write the error in, or `null` - * - * Returns: Whether `trailingArgs` match `p`. - */ -private extern(D) MATCH argumentMatchParameter (TypeFunction tf, Parameter p, - Expression arg, ubyte wildmatch, int flag, Scope* sc, const(char)** pMessage) -{ - //printf("arg: %s, type: %s\n", arg.toChars(), arg.type.toChars()); - MATCH m; - Type targ = arg.type; - Type tprm = wildmatch ? p.type.substWildTo(wildmatch) : p.type; - - if (p.isLazy() && tprm.ty == Tvoid && targ.ty != Tvoid) - m = MATCH.convert; - else if (flag) - { - // for partial ordering, value is an irrelevant mockup, just look at the type - m = targ.implicitConvTo(tprm); - } - else - { - const isRef = p.isReference(); - StructDeclaration argStruct, prmStruct; - - // first look for a copy constructor - if (arg.isLvalue() && !isRef && targ.ty == Tstruct && tprm.ty == Tstruct) - { - // if the argument and the parameter are of the same unqualified struct type - argStruct = (cast(TypeStruct)targ).sym; - prmStruct = (cast(TypeStruct)tprm).sym; - } - - // check if the copy constructor may be called to copy the argument - if (argStruct && argStruct == prmStruct && argStruct.hasCopyCtor) - { - if (!isCopyConstructorCallable(argStruct, arg, tprm, sc, pMessage)) - return MATCH.nomatch; - m = MATCH.exact; - } - else - { - import dmd.dcast : cimplicitConvTo; - m = (sc && sc.flags & SCOPE.Cfile) ? arg.cimplicitConvTo(tprm) : arg.implicitConvTo(tprm); - } - } - - // Non-lvalues do not match ref or out parameters - if (p.isReference()) - { - // https://issues.dlang.org/show_bug.cgi?id=13783 - // Don't use toBasetype() to handle enum types. - Type ta = targ; - Type tp = tprm; - //printf("fparam[%d] ta = %s, tp = %s\n", u, ta.toChars(), tp.toChars()); - - if (m && !arg.isLvalue()) - { - if (p.storageClass & STC.out_) - { - if (pMessage) *pMessage = tf.getParamError(arg, p); - return MATCH.nomatch; - } - - if (arg.op == EXP.string_ && tp.ty == Tsarray) - { - if (ta.ty != Tsarray) - { - Type tn = tp.nextOf().castMod(ta.nextOf().mod); - dinteger_t dim = (cast(StringExp)arg).len; - ta = tn.sarrayOf(dim); - } - } - else if (arg.op == EXP.slice && tp.ty == Tsarray) - { - // Allow conversion from T[lwr .. upr] to ref T[upr-lwr] - if (ta.ty != Tsarray) - { - Type tn = ta.nextOf(); - dinteger_t dim = (cast(TypeSArray)tp).dim.toUInteger(); - ta = tn.sarrayOf(dim); - } - } - else if ((p.storageClass & STC.in_) && global.params.previewIn) - { - // Allow converting a literal to an `in` which is `ref` - if (arg.op == EXP.arrayLiteral && tp.ty == Tsarray) - { - Type tn = tp.nextOf(); - dinteger_t dim = (cast(TypeSArray)tp).dim.toUInteger(); - ta = tn.sarrayOf(dim); - } - - // Need to make this a rvalue through a temporary - m = MATCH.convert; - } - else if (global.params.rvalueRefParam != FeatureState.enabled || - p.storageClass & STC.out_ || - !arg.type.isCopyable()) // can't copy to temp for ref parameter - { - if (pMessage) *pMessage = tf.getParamError(arg, p); - return MATCH.nomatch; - } - else - { - /* in functionParameters() we'll convert this - * rvalue into a temporary - */ - m = MATCH.convert; - } - } - - /* If the match is not already perfect or if the arg - is not a lvalue then try the `alias this` chain - see https://issues.dlang.org/show_bug.cgi?id=15674 - and https://issues.dlang.org/show_bug.cgi?id=21905 - */ - if (ta != tp || !arg.isLvalue()) - { - Type firsttab = ta.toBasetype(); - while (1) - { - Type tab = ta.toBasetype(); - Type tat = tab.aliasthisOf(); - if (!tat || !tat.implicitConvTo(tprm)) - break; - if (tat == tab || tat == firsttab) - break; - ta = tat; - } - } - - /* A ref variable should work like a head-const reference. - * e.g. disallows: - * ref T <- an lvalue of const(T) argument - * ref T[dim] <- an lvalue of const(T[dim]) argument - */ - if (!ta.constConv(tp)) - { - if (pMessage) *pMessage = tf.getParamError(arg, p); - return MATCH.nomatch; - } - } - return m; -} - -/** - * Match the remaining arguments `trailingArgs` with parameter `p`. - * - * Assume we already checked that `p` is the last parameter of `tf`, - * and we want to know whether the arguments would match `p`. - * - * Params: - * tf = The `TypeFunction`, only used for error reporting - * p = The last parameter of `tf` which is variadic - * trailingArgs = The remaining arguments that should match `p` - * pMessage = A buffer to write the error in, or `null` - * - * Returns: Whether `trailingArgs` match `p`. - */ -private extern(D) MATCH matchTypeSafeVarArgs(TypeFunction tf, Parameter p, - Expression[] trailingArgs, const(char)** pMessage) -{ - Type tb = p.type.toBasetype(); - - switch (tb.ty) - { - case Tsarray: - TypeSArray tsa = cast(TypeSArray)tb; - dinteger_t sz = tsa.dim.toInteger(); - if (sz != trailingArgs.length) - { - if (pMessage) - *pMessage = tf.getMatchError("expected %llu variadic argument(s), not %zu", - sz, trailingArgs.length); - return MATCH.nomatch; - } - goto case Tarray; - case Tarray: - { - MATCH match = MATCH.exact; - TypeArray ta = cast(TypeArray)tb; - foreach (arg; trailingArgs) - { - MATCH m; - assert(arg); - - /* If lazy array of delegates, - * convert arg(s) to delegate(s) - */ - Type tret = p.isLazyArray(); - if (tret) - { - if (ta.next.equals(arg.type)) - m = MATCH.exact; - else if (tret.toBasetype().ty == Tvoid) - m = MATCH.convert; - else - { - m = arg.implicitConvTo(tret); - if (m == MATCH.nomatch) - m = arg.implicitConvTo(ta.next); - } - } - else - m = arg.implicitConvTo(ta.next); - - if (m == MATCH.nomatch) - { - if (pMessage) *pMessage = tf.getParamError(arg, p); - return MATCH.nomatch; - } - if (m < match) - match = m; - } - return match; - } - case Tclass: - // We leave it up to the actual constructor call to do the matching. - return MATCH.exact; - - default: - // We can have things as `foo(int[int] wat...)` but they only match - // with an associative array proper. - if (pMessage && trailingArgs.length) *pMessage = tf.getParamError(trailingArgs[0], p); - return MATCH.nomatch; - } -} - /** * Creates an appropriate vector type for `tv` that will hold one boolean * result for each element of the vector type. The result of vector comparisons diff --git a/dmd/typesem.d b/dmd/typesem.d index eec9e9f3360..574e54cfb7b 100644 --- a/dmd/typesem.d +++ b/dmd/typesem.d @@ -486,6 +486,529 @@ Expression typeToExpression(Type t) } } +/******************************** + * 'args' are being matched to function type 'tf' + * Determine match level. + * Params: + * tf = function type + * tthis = type of `this` pointer, null if not member function + * argumentList = arguments to function call + * flag = 1: performing a partial ordering match + * pMessage = address to store error message, or null + * sc = context + * Returns: + * MATCHxxxx + */ +extern (D) MATCH callMatch(TypeFunction tf, Type tthis, ArgumentList argumentList, int flag = 0, const(char)** pMessage = null, Scope* sc = null) +{ + //printf("TypeFunction::callMatch() %s\n", tf.toChars()); + MATCH match = MATCH.exact; // assume exact match + ubyte wildmatch = 0; + + if (tthis) + { + Type t = tthis; + if (t.toBasetype().ty == Tpointer) + t = t.toBasetype().nextOf(); // change struct* to struct + if (t.mod != tf.mod) + { + if (MODimplicitConv(t.mod, tf.mod)) + match = MATCH.constant; + else if ((tf.mod & MODFlags.wild) && MODimplicitConv(t.mod, (tf.mod & ~MODFlags.wild) | MODFlags.const_)) + { + match = MATCH.constant; + } + else + return MATCH.nomatch; + } + if (tf.isWild()) + { + if (t.isWild()) + wildmatch |= MODFlags.wild; + else if (t.isConst()) + wildmatch |= MODFlags.const_; + else if (t.isImmutable()) + wildmatch |= MODFlags.immutable_; + else + wildmatch |= MODFlags.mutable; + } + } + + ParameterList* parameterList = &tf.parameterList; + const nparams = parameterList.length; + if (argumentList.length > nparams) + { + if (parameterList.varargs == VarArg.none) + { + // suppress early exit if an error message is wanted, + // so we can check any matching args are valid + if (!pMessage) + return MATCH.nomatch; + } + // too many args; no match + match = MATCH.convert; // match ... with a "conversion" match level + } + + // https://issues.dlang.org/show_bug.cgi?id=22997 + if (parameterList.varargs == VarArg.none && nparams > argumentList.length && !parameterList.hasDefaultArgs) + { + OutBuffer buf; + buf.printf("too few arguments, expected %d, got %d", cast(int)nparams, cast(int)argumentList.length); + if (pMessage) + *pMessage = buf.extractChars(); + return MATCH.nomatch; + } + auto resolvedArgs = tf.resolveNamedArgs(argumentList, pMessage); + Expression[] args; + if (!resolvedArgs) + { + if (!pMessage || *pMessage) + return MATCH.nomatch; + + // if no message was provided, it was because of overflow which will be diagnosed below + match = MATCH.nomatch; + args = argumentList.arguments ? (*argumentList.arguments)[] : null; + } + else + { + args = (*resolvedArgs)[]; + } + + foreach (u, p; *parameterList) + { + if (u >= args.length) + break; + + Expression arg = args[u]; + if (!arg) + continue; // default argument + + Type tprm = p.type; + Type targ = arg.type; + + if (!(p.isLazy() && tprm.ty == Tvoid && targ.ty != Tvoid)) + { + const isRef = p.isReference(); + wildmatch |= targ.deduceWild(tprm, isRef); + } + } + if (wildmatch) + { + /* Calculate wild matching modifier + */ + if (wildmatch & MODFlags.const_ || wildmatch & (wildmatch - 1)) + wildmatch = MODFlags.const_; + else if (wildmatch & MODFlags.immutable_) + wildmatch = MODFlags.immutable_; + else if (wildmatch & MODFlags.wild) + wildmatch = MODFlags.wild; + else + { + assert(wildmatch & MODFlags.mutable); + wildmatch = MODFlags.mutable; + } + } + + foreach (u, p; *parameterList) + { + MATCH m; + + assert(p); + + // One or more arguments remain + if (u < args.length) + { + Expression arg = args[u]; + if (!arg) + continue; // default argument + m = argumentMatchParameter(tf, p, arg, wildmatch, flag, sc, pMessage); + } + else if (p.defaultArg) + continue; + + /* prefer matching the element type rather than the array + * type when more arguments are present with T[]... + */ + if (parameterList.varargs == VarArg.typesafe && u + 1 == nparams && args.length > nparams) + goto L1; + + //printf("\tm = %d\n", m); + if (m == MATCH.nomatch) // if no match + { + L1: + if (parameterList.varargs == VarArg.typesafe && u + 1 == nparams) // if last varargs param + { + auto trailingArgs = args[u .. $]; + if (auto vmatch = matchTypeSafeVarArgs(tf, p, trailingArgs, pMessage)) + return vmatch < match ? vmatch : match; + // Error message was already generated in `matchTypeSafeVarArgs` + return MATCH.nomatch; + } + if (pMessage && u >= args.length) + *pMessage = tf.getMatchError("missing argument for parameter #%d: `%s`", + u + 1, parameterToChars(p, tf, false)); + // If an error happened previously, `pMessage` was already filled + else if (pMessage && !*pMessage) + *pMessage = tf.getParamError(args[u], p); + + return MATCH.nomatch; + } + if (m < match) + match = m; // pick worst match + } + + if (pMessage && !parameterList.varargs && args.length > nparams) + { + // all parameters had a match, but there are surplus args + *pMessage = tf.getMatchError("expected %d argument(s), not %d", nparams, args.length); + return MATCH.nomatch; + } + //printf("match = %d\n", match); + return match; +} + +/** + * Used by `callMatch` to check if the copy constructor may be called to + * copy the argument + * + * This is done by seeing if a call to the copy constructor can be made: + * ``` + * typeof(tprm) __copytmp; + * copytmp.__copyCtor(arg); + * ``` + */ +private extern(D) bool isCopyConstructorCallable (StructDeclaration argStruct, + Expression arg, Type tprm, Scope* sc, const(char)** pMessage) +{ + auto tmp = new VarDeclaration(arg.loc, tprm, Identifier.generateId("__copytmp"), null); + tmp.storage_class = STC.rvalue | STC.temp | STC.ctfe; + tmp.dsymbolSemantic(sc); + Expression ve = new VarExp(arg.loc, tmp); + Expression e = new DotIdExp(arg.loc, ve, Id.ctor); + e = new CallExp(arg.loc, e, arg); + //printf("e = %s\n", e.toChars()); + if (.trySemantic(e, sc)) + return true; + + if (pMessage) + { + /* https://issues.dlang.org/show_bug.cgi?id=22202 + * + * If a function was deduced by semantic on the CallExp, + * it means that resolveFuncCall completed succesfully. + * Therefore, there exists a callable copy constructor, + * however, it cannot be called because scope constraints + * such as purity, safety or nogc. + */ + OutBuffer buf; + auto callExp = e.isCallExp(); + if (auto f = callExp.f) + { + char[] s; + if (!f.isPure && sc.func.setImpure()) + s ~= "pure "; + if (!f.isSafe() && !f.isTrusted() && sc.setUnsafe()) + s ~= "@safe "; + if (!f.isNogc && sc.func.setGC(arg.loc, null)) + s ~= "nogc "; + if (s) + { + s[$-1] = '\0'; + buf.printf("`%s` copy constructor cannot be called from a `%s` context", f.type.toChars(), s.ptr); + } + else if (f.isGenerated() && f.isDisabled()) + { + /* https://issues.dlang.org/show_bug.cgi?id=23097 + * Compiler generated copy constructor failed. + */ + buf.printf("generating a copy constructor for `struct %s` failed, therefore instances of it are uncopyable", + argStruct.toChars()); + } + else + { + /* Although a copy constructor may exist, no suitable match was found. + * i.e: `inout` constructor creates `const` object, not mutable. + * Fallback to using the original generic error before https://issues.dlang.org/show_bug.cgi?id=22202. + */ + goto Lnocpctor; + } + } + else + { + Lnocpctor: + buf.printf("`struct %s` does not define a copy constructor for `%s` to `%s` copies", + argStruct.toChars(), arg.type.toChars(), tprm.toChars()); + } + + *pMessage = buf.extractChars(); + } + return false; +} + +/** + * Match a single parameter to an argument. + * + * This function is called by `TypeFunction.callMatch` while iterating over + * the list of parameter. Here we check if `arg` is a match for `p`, + * which is mostly about checking if `arg.type` converts to `p`'s type + * and some check about value reference. + * + * Params: + * tf = The `TypeFunction`, only used for error reporting + * p = The parameter of `tf` being matched + * arg = Argument being passed (bound) to `p` + * wildmatch = Wild (`inout`) matching level, derived from the full argument list + * flag = A non-zero value means we're doing a partial ordering check + * (no value semantic check) + * sc = Scope we are in + * pMessage = A buffer to write the error in, or `null` + * + * Returns: Whether `trailingArgs` match `p`. + */ +private extern(D) MATCH argumentMatchParameter (TypeFunction tf, Parameter p, + Expression arg, ubyte wildmatch, int flag, Scope* sc, const(char)** pMessage) +{ + //printf("arg: %s, type: %s\n", arg.toChars(), arg.type.toChars()); + MATCH m; + Type targ = arg.type; + Type tprm = wildmatch ? p.type.substWildTo(wildmatch) : p.type; + + if (p.isLazy() && tprm.ty == Tvoid && targ.ty != Tvoid) + m = MATCH.convert; + else if (flag) + { + // for partial ordering, value is an irrelevant mockup, just look at the type + m = targ.implicitConvTo(tprm); + } + else + { + const isRef = p.isReference(); + StructDeclaration argStruct, prmStruct; + + // first look for a copy constructor + if (arg.isLvalue() && !isRef && targ.ty == Tstruct && tprm.ty == Tstruct) + { + // if the argument and the parameter are of the same unqualified struct type + argStruct = (cast(TypeStruct)targ).sym; + prmStruct = (cast(TypeStruct)tprm).sym; + } + + // check if the copy constructor may be called to copy the argument + if (argStruct && argStruct == prmStruct && argStruct.hasCopyCtor) + { + if (!isCopyConstructorCallable(argStruct, arg, tprm, sc, pMessage)) + return MATCH.nomatch; + m = MATCH.exact; + } + else + { + import dmd.dcast : cimplicitConvTo; + m = (sc && sc.flags & SCOPE.Cfile) ? arg.cimplicitConvTo(tprm) : arg.implicitConvTo(tprm); + } + } + + // Non-lvalues do not match ref or out parameters + if (p.isReference()) + { + // https://issues.dlang.org/show_bug.cgi?id=13783 + // Don't use toBasetype() to handle enum types. + Type ta = targ; + Type tp = tprm; + //printf("fparam[%d] ta = %s, tp = %s\n", u, ta.toChars(), tp.toChars()); + + if (m && !arg.isLvalue()) + { + if (p.storageClass & STC.out_) + { + if (pMessage) *pMessage = tf.getParamError(arg, p); + return MATCH.nomatch; + } + + if (arg.op == EXP.string_ && tp.ty == Tsarray) + { + if (ta.ty != Tsarray) + { + Type tn = tp.nextOf().castMod(ta.nextOf().mod); + dinteger_t dim = (cast(StringExp)arg).len; + ta = tn.sarrayOf(dim); + } + } + else if (arg.op == EXP.slice && tp.ty == Tsarray) + { + // Allow conversion from T[lwr .. upr] to ref T[upr-lwr] + if (ta.ty != Tsarray) + { + Type tn = ta.nextOf(); + dinteger_t dim = (cast(TypeSArray)tp).dim.toUInteger(); + ta = tn.sarrayOf(dim); + } + } + else if ((p.storageClass & STC.in_) && global.params.previewIn) + { + // Allow converting a literal to an `in` which is `ref` + if (arg.op == EXP.arrayLiteral && tp.ty == Tsarray) + { + Type tn = tp.nextOf(); + dinteger_t dim = (cast(TypeSArray)tp).dim.toUInteger(); + ta = tn.sarrayOf(dim); + } + + // Need to make this a rvalue through a temporary + m = MATCH.convert; + } + else if (global.params.rvalueRefParam != FeatureState.enabled || + p.storageClass & STC.out_ || + !arg.type.isCopyable()) // can't copy to temp for ref parameter + { + if (pMessage) *pMessage = tf.getParamError(arg, p); + return MATCH.nomatch; + } + else + { + /* in functionParameters() we'll convert this + * rvalue into a temporary + */ + m = MATCH.convert; + } + } + + /* If the match is not already perfect or if the arg + is not a lvalue then try the `alias this` chain + see https://issues.dlang.org/show_bug.cgi?id=15674 + and https://issues.dlang.org/show_bug.cgi?id=21905 + */ + if (ta != tp || !arg.isLvalue()) + { + Type firsttab = ta.toBasetype(); + while (1) + { + Type tab = ta.toBasetype(); + Type tat = tab.aliasthisOf(); + if (!tat || !tat.implicitConvTo(tprm)) + break; + if (tat == tab || tat == firsttab) + break; + ta = tat; + } + } + + /* A ref variable should work like a head-const reference. + * e.g. disallows: + * ref T <- an lvalue of const(T) argument + * ref T[dim] <- an lvalue of const(T[dim]) argument + */ + if (!ta.constConv(tp)) + { + if (pMessage) *pMessage = tf.getParamError(arg, p); + return MATCH.nomatch; + } + } + return m; +} + +// arguments get specially formatted +private const(char)* getParamError(TypeFunction tf, Expression arg, Parameter par) +{ + if (global.gag && !global.params.v.showGaggedErrors) + return null; + // show qualification when toChars() is the same but types are different + // https://issues.dlang.org/show_bug.cgi?id=19948 + // when comparing the type with strcmp, we need to drop the qualifier + bool qual = !arg.type.mutableOf().equals(par.type.mutableOf()) && + strcmp(arg.type.mutableOf().toChars(), par.type.mutableOf().toChars()) == 0; + auto at = qual ? arg.type.toPrettyChars(true) : arg.type.toChars(); + OutBuffer buf; + // only mention rvalue if it's relevant + const rv = !arg.isLvalue() && par.isReference(); + buf.printf("cannot pass %sargument `%s` of type `%s` to parameter `%s`", + rv ? "rvalue ".ptr : "".ptr, arg.toChars(), at, + parameterToChars(par, tf, qual)); + return buf.extractChars(); +} + +/** + * Match the remaining arguments `trailingArgs` with parameter `p`. + * + * Assume we already checked that `p` is the last parameter of `tf`, + * and we want to know whether the arguments would match `p`. + * + * Params: + * tf = The `TypeFunction`, only used for error reporting + * p = The last parameter of `tf` which is variadic + * trailingArgs = The remaining arguments that should match `p` + * pMessage = A buffer to write the error in, or `null` + * + * Returns: Whether `trailingArgs` match `p`. + */ +private extern(D) MATCH matchTypeSafeVarArgs(TypeFunction tf, Parameter p, + Expression[] trailingArgs, const(char)** pMessage) +{ + Type tb = p.type.toBasetype(); + + switch (tb.ty) + { + case Tsarray: + TypeSArray tsa = cast(TypeSArray)tb; + dinteger_t sz = tsa.dim.toInteger(); + if (sz != trailingArgs.length) + { + if (pMessage) + *pMessage = tf.getMatchError("expected %llu variadic argument(s), not %zu", + sz, trailingArgs.length); + return MATCH.nomatch; + } + goto case Tarray; + case Tarray: + { + MATCH match = MATCH.exact; + TypeArray ta = cast(TypeArray)tb; + foreach (arg; trailingArgs) + { + MATCH m; + assert(arg); + + /* If lazy array of delegates, + * convert arg(s) to delegate(s) + */ + Type tret = p.isLazyArray(); + if (tret) + { + if (ta.next.equals(arg.type)) + m = MATCH.exact; + else if (tret.toBasetype().ty == Tvoid) + m = MATCH.convert; + else + { + m = arg.implicitConvTo(tret); + if (m == MATCH.nomatch) + m = arg.implicitConvTo(ta.next); + } + } + else + m = arg.implicitConvTo(ta.next); + + if (m == MATCH.nomatch) + { + if (pMessage) *pMessage = tf.getParamError(arg, p); + return MATCH.nomatch; + } + if (m < match) + match = m; + } + return match; + } + case Tclass: + // We leave it up to the actual constructor call to do the matching. + return MATCH.exact; + + default: + // We can have things as `foo(int[int] wat...)` but they only match + // with an associative array proper. + if (pMessage && trailingArgs.length) *pMessage = tf.getParamError(trailingArgs[0], p); + return MATCH.nomatch; + } +} + /****************************************** * Perform semantic analysis on a type. * Params: From ad91b5832d998ef39b357e76132873e8b89cac41 Mon Sep 17 00:00:00 2001 From: Martin Kinkelin Date: Fri, 15 Dec 2023 15:57:24 +0100 Subject: [PATCH 109/215] Fix Phobos CI regression --- runtime/druntime/posix.mak | 3 +++ 1 file changed, 3 insertions(+) diff --git a/runtime/druntime/posix.mak b/runtime/druntime/posix.mak index 4de5d7dded4..3cfc8bff49e 100644 --- a/runtime/druntime/posix.mak +++ b/runtime/druntime/posix.mak @@ -355,6 +355,9 @@ $(IMPDIR)/%.h : src/%.h $(DMD_DIR)/../generated/$(OS)/$(BUILD)/$(MODEL)/dmd: $(MAKE) -C $(DMD_DIR)/.. dmd BUILD=$(BUILD) OS=$(OS) MODEL=$(MODEL) DMD="" +# alias using the absolute path (the Phobos Makefile specifies an absolute path) +$(abspath $(DMD_DIR)/../generated/$(OS)/$(BUILD)/$(MODEL)/dmd): $(DMD_DIR)/../generated/$(OS)/$(BUILD)/$(MODEL)/dmd + ################### C/ASM Targets ############################ $(ROOT)/%.o : src/rt/%.c $(DMD) From d47c3faa08c48a57bb6a974fa57c16e8e56a8d54 Mon Sep 17 00:00:00 2001 From: Martin Kinkelin Date: Sun, 10 Dec 2023 19:39:36 +0100 Subject: [PATCH 110/215] Azure CI: Migrate from legacy MODEL=32mscoff to MODEL=32 Incl. fixing up the d_do_test.d tool to work properly with MODEL=32 on Windows. And somewhat improve the documentation of MODEL=32omf, nowadays used for the 32-bit OMF toolchain. --- tests/dmd/README.md | 3 ++- tests/dmd/runnable/test23011.c | 2 +- tests/dmd/tools/d_do_test.d | 25 ++++++++++++++++++------- 3 files changed, 21 insertions(+), 9 deletions(-) diff --git a/tests/dmd/README.md b/tests/dmd/README.md index 19952856d6e..f0827f258f7 100644 --- a/tests/dmd/README.md +++ b/tests/dmd/README.md @@ -204,6 +204,7 @@ Valid platforms: Valid models: - 32 - 32mscoff (windows only) +- 32omf (windows only) - 64 Note that test parameters *MUST* be followed by a colon (intermediate whitespace is allowed). @@ -423,7 +424,7 @@ depend on the current platform and target: Supported conditions: - OS: posix, windows, ... - - Model: 64, 32mscoff and 32 (also matches 32mscoff) + - Model: 64, 32mscoff, 32omf and 32 (also matches 32mscoff + 32omf) $r:$ any text matching (using $ inside of is not supported, use multiple regexes instead) diff --git a/tests/dmd/runnable/test23011.c b/tests/dmd/runnable/test23011.c index e6c320e8cd4..4c49747021e 100644 --- a/tests/dmd/runnable/test23011.c +++ b/tests/dmd/runnable/test23011.c @@ -1,4 +1,4 @@ -/* DISABLED: win32 win32mscoff win64 osx32 osx64 +/* DISABLED: win osx */ /* https://issues.dlang.org/show_bug.cgi?id=23011 diff --git a/tests/dmd/tools/d_do_test.d b/tests/dmd/tools/d_do_test.d index fdb7e00ede2..b642c4d9932 100755 --- a/tests/dmd/tools/d_do_test.d +++ b/tests/dmd/tools/d_do_test.d @@ -172,6 +172,15 @@ immutable(EnvData) processEnvironment() envData.compiler = "dmd"; //should be replaced for other compilers envData.ccompiler = environment.get("CC"); envData.model = envGetRequired("MODEL"); + if (envData.os == "windows" && envData.model == "32") + { + // FIXME: we need to translate the default 32-bit model (COFF) on Windows to legacy `32mscoff`. + // Reason: OMF-specific tests are currently specified like this: + // DISABLED: win32mscoff win64 … + // and `DISABLED: win32` would disable it for `win32omf` too. + // So we'd need something like an `ENABLED: win32omf` parameter to restrict tests to specific platforms. + envData.model = "32mscoff"; + } envData.required_args = environment.get("REQUIRED_ARGS"); envData.dobjc = environment.get("D_OBJC") == "1"; envData.coverage_build = environment.get("DMD_TEST_COVERAGE") == "1"; @@ -190,6 +199,8 @@ immutable(EnvData) processEnvironment() envData.ccompiler = "dmc"; else if (envData.model == "64") envData.ccompiler = `C:\"Program Files (x86)"\"Microsoft Visual Studio 10.0"\VC\bin\amd64\cl.exe`; + else if (envData.model == "32mscoff") + envData.ccompiler = `C:\"Program Files (x86)"\"Microsoft Visual Studio 10.0"\VC\bin\amd64_x86\cl.exe`; else { writeln("Unknown $OS$MODEL combination: ", envData.os, envData.model); @@ -519,8 +530,8 @@ private bool consumeNextToken(ref string file, const string token, ref const Env file = file.stripLeft!(ch => ch == ' '); // Don't read line breaks // Check if the current environment matches an entry in oss, which can either - // be an OS (e.g. "linux") or a combination of OS + MODEL (e.g. "windows32"). - // The latter is important on windows because m32 might require other + // be an OS (e.g. "linux") or a combination of OS + MODEL (e.g. "windows32omf"). + // The latter is important on windows because m32omf might require other // parameters than m32mscoff/m64. if (!oss.canFind!(o => o.skipOver(envData.os) && (o.empty || o == envData.model))) continue; // Parameter was skipped @@ -618,9 +629,9 @@ string getDisabledReason(string[] disabledPlatforms, const ref EnvData envData) unittest { - immutable EnvData win32 = { os: "windows", model: "32", }; - immutable EnvData win32mscoff = { os: "windows", model: "32mscoff", }; - immutable EnvData win64 = { os: "windows", model: "64", }; + immutable EnvData win32omf = { os: "windows", model: "32omf" }; + immutable EnvData win32mscoff = { os: "windows", model: "32mscoff" }; + immutable EnvData win64 = { os: "windows", model: "64" }; assert(getDisabledReason(null, win64) is null); @@ -631,10 +642,10 @@ unittest assert(getDisabledReason([ "linux", "win32" ], win64) is null); assert(getDisabledReason([ "win32mscoff" ], win32mscoff) == "on win32mscoff"); - assert(getDisabledReason([ "win32mscoff" ], win32) is null); + assert(getDisabledReason([ "win32mscoff" ], win32omf) is null); assert(getDisabledReason([ "win32" ], win32mscoff) == "on win32"); - assert(getDisabledReason([ "win32" ], win32) == "on win32"); + assert(getDisabledReason([ "win32" ], win32omf) == "on win32"); } /** * Reads the test configuration from the source code (using `findTestParameter` and From 3d98270fc2781d6ed96fc551196582ed3f73e956 Mon Sep 17 00:00:00 2001 From: Martin Kinkelin Date: Sat, 16 Dec 2023 03:16:09 +0100 Subject: [PATCH 111/215] Windows: Don't apply OMF-specific 16 MB static data limit to 32-bit COFF --- dmd/target.d | 2 +- tests/dmd/fail_compilation/fail19890a.d | 2 +- tests/dmd/fail_compilation/fail19890b.d | 2 +- tests/dmd/fail_compilation/fail4611.d | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/dmd/target.d b/dmd/target.d index e3ad903180a..66faa035a2f 100644 --- a/dmd/target.d +++ b/dmd/target.d @@ -446,7 +446,7 @@ extern (C++) struct Target realsize = 10; realpad = 0; realalignsize = 2; - if (ptrsize == 4) + if (omfobj) { /* Optlink cannot deal with individual data chunks * larger than 16Mb diff --git a/tests/dmd/fail_compilation/fail19890a.d b/tests/dmd/fail_compilation/fail19890a.d index d4da11604fa..9b984961f33 100644 --- a/tests/dmd/fail_compilation/fail19890a.d +++ b/tests/dmd/fail_compilation/fail19890a.d @@ -1,7 +1,7 @@ /* TEST_OUTPUT: --- -fail_compilation/fail19890a.d(8): Error: `void[$n$$?:64=LU$]` size 1 * $n$ exceeds $?:windows+32=0x1000000|0x7fffffff$ size limit for static array +fail_compilation/fail19890a.d(8): Error: `void[$n$$?:64=LU$]` size 1 * $n$ exceeds $?:windows+32omf=0x1000000|0x7fffffff$ size limit for static array --- */ diff --git a/tests/dmd/fail_compilation/fail19890b.d b/tests/dmd/fail_compilation/fail19890b.d index f4a5dada2c8..19081d95871 100644 --- a/tests/dmd/fail_compilation/fail19890b.d +++ b/tests/dmd/fail_compilation/fail19890b.d @@ -1,7 +1,7 @@ /* TEST_OUTPUT: --- -fail_compilation/fail19890b.d(8): Error: `void[$n$$?:64=LU$]` size 1 * $n$ exceeds $?:windows+32=0x1000000|0x7fffffff$ size limit for static array +fail_compilation/fail19890b.d(8): Error: `void[$n$$?:64=LU$]` size 1 * $n$ exceeds $?:windows+32omf=0x1000000|0x7fffffff$ size limit for static array --- */ diff --git a/tests/dmd/fail_compilation/fail4611.d b/tests/dmd/fail_compilation/fail4611.d index 030c47c69ca..04adf13f5e7 100644 --- a/tests/dmd/fail_compilation/fail4611.d +++ b/tests/dmd/fail_compilation/fail4611.d @@ -1,7 +1,7 @@ /* TEST_OUTPUT: --- -fail_compilation/fail4611.d(15): Error: `Vec[$n$]` size 4 * $n$ exceeds $?:windows+32=0x1000000|0x7fffffff$ size limit for static array +fail_compilation/fail4611.d(15): Error: `Vec[$n$]` size 4 * $n$ exceeds $?:windows+32omf=0x1000000|0x7fffffff$ size limit for static array --- */ From 6e55e7c87dd50d8eba49b1f1f6b4ff6426e29484 Mon Sep 17 00:00:00 2001 From: Walter Bright Date: Sat, 16 Dec 2023 13:11:35 -0800 Subject: [PATCH 112/215] fix Issue 23629 - importC: Need to support code coverage analysis (dlang/dmd!15913) --- tests/dmd/runnable/cov2.d | 12 ++++++++++++ tests/dmd/runnable/extra-files/runnable-cov2.lst | 12 ++++++++++++ tests/dmd/runnable/imports/ccov2.c | 7 +++++++ 3 files changed, 31 insertions(+) create mode 100644 tests/dmd/runnable/imports/ccov2.c diff --git a/tests/dmd/runnable/cov2.d b/tests/dmd/runnable/cov2.d index 875fb3a3242..9ce761d2d60 100644 --- a/tests/dmd/runnable/cov2.d +++ b/tests/dmd/runnable/cov2.d @@ -49,6 +49,17 @@ void test3() total += i; } +/***************************************************/ +// https://issues.dlang.org/show_bug.cgi?id=24264 +// EXTRA_SOURCES: imports/ccov2.c + +import ccov2; + +int test24264() +{ + return def(); +} + /***************************************************/ int main(string[] args) @@ -57,5 +68,6 @@ int main(string[] args) test1(); test2(); test3(); + test24264(); return 0; } diff --git a/tests/dmd/runnable/extra-files/runnable-cov2.lst b/tests/dmd/runnable/extra-files/runnable-cov2.lst index 5f3a0898177..34b1657ca01 100644 --- a/tests/dmd/runnable/extra-files/runnable-cov2.lst +++ b/tests/dmd/runnable/extra-files/runnable-cov2.lst @@ -47,6 +47,17 @@ 1| long total = 0; 20000002| for (size_t i = 0; i < 10_000_000; i++) 10000000| total += i; + |} + | + |/***************************************************/ + |// https://issues.dlang.org/show_bug.cgi?id=24264 + |// EXTRA_SOURCES: imports/ccov2.c + | + |import ccov2; + | + |int test24264() + |{ + 1| return def(); |} | |/***************************************************/ @@ -57,5 +68,6 @@ 1| test1(); 1| test2(); 1| test3(); + 1| test24264(); 1| return 0; |} diff --git a/tests/dmd/runnable/imports/ccov2.c b/tests/dmd/runnable/imports/ccov2.c new file mode 100644 index 00000000000..855002de6eb --- /dev/null +++ b/tests/dmd/runnable/imports/ccov2.c @@ -0,0 +1,7 @@ +int def() +{ + int i; + for (i = 0; i < 10; ++i) + ; + return i; +} From d3b5ed1c798a3fc3558602e9aa1539063bc7f109 Mon Sep 17 00:00:00 2001 From: Dennis Korpel Date: Wed, 13 Dec 2023 18:39:05 +0100 Subject: [PATCH 113/215] Fix 24281 - Segfault with missing field after named argument --- dmd/initsem.d | 5 +++++ .../named_arguments_struct_literal.d | 15 +++++++++++++++ 2 files changed, 20 insertions(+) create mode 100644 tests/dmd/fail_compilation/named_arguments_struct_literal.d diff --git a/dmd/initsem.d b/dmd/initsem.d index 1d7f56ed44a..19d576d4660 100644 --- a/dmd/initsem.d +++ b/dmd/initsem.d @@ -1574,6 +1574,11 @@ Expressions* resolveStructLiteralNamedArgs(StructDeclaration sd, Type t, Scope* cast(int) nfields, nfields != 1 ? "s".ptr : "".ptr); return null; } + if (fieldi >= nfields) + { + error(argLoc, "trying to initialize past the last field `%s` of `%s`", sd.fields[nfields - 1].toChars(), sd.toChars()); + return null; + } VarDeclaration vd = sd.fields[fieldi]; if (elems[fieldi]) diff --git a/tests/dmd/fail_compilation/named_arguments_struct_literal.d b/tests/dmd/fail_compilation/named_arguments_struct_literal.d new file mode 100644 index 00000000000..5b8f2c621cc --- /dev/null +++ b/tests/dmd/fail_compilation/named_arguments_struct_literal.d @@ -0,0 +1,15 @@ +/** +TEST_OUTPUT: +--- +fail_compilation/named_arguments_struct_literal.d(14): Error: trying to initialize past the last field `z` of `S` +--- +*/ + +// https://issues.dlang.org/show_bug.cgi?id=24281 + +struct S { int y, z = 3; } + +S s = S( + z: 2, + 3, +); From fa83ca0c8f5942c399ac5e9ee6f2c769f89ae505 Mon Sep 17 00:00:00 2001 From: Walter Bright Date: Sat, 16 Dec 2023 22:27:04 -0800 Subject: [PATCH 114/215] statementsem.d: remove some casts --- dmd/statementsem.d | 67 +++++++++++++++++++++++----------------------- 1 file changed, 33 insertions(+), 34 deletions(-) diff --git a/dmd/statementsem.d b/dmd/statementsem.d index fcc606b6dd5..f3afa42b0b1 100644 --- a/dmd/statementsem.d +++ b/dmd/statementsem.d @@ -568,8 +568,8 @@ Statement statementSemanticVisit(Statement s, Scope* sc) ds._body = ds._body.semanticScope(sc, ds, ds, null); sc.inLoop = inLoopSave; - if (ds.condition.op == EXP.dotIdentifier) - (cast(DotIdExp)ds.condition).noderef = true; + if (auto dotid = ds.condition.isDotIdExp()) + dotid.noderef = true; // check in syntax level ds.condition = checkAssignmentAsCondition(ds.condition, sc); @@ -641,8 +641,8 @@ Statement statementSemanticVisit(Statement s, Scope* sc) if (fs.condition) { - if (fs.condition.op == EXP.dotIdentifier) - (cast(DotIdExp)fs.condition).noderef = true; + if (auto dotid = fs.condition.isDotIdExp()) + dotid.noderef = true; // check in syntax level fs.condition = checkAssignmentAsCondition(fs.condition, sc); @@ -729,8 +729,8 @@ Statement statementSemanticVisit(Statement s, Scope* sc) if (fs.aggr.op == EXP.error) return setError(); Expression oaggr = fs.aggr; // remember original for error messages - if (fs.aggr.type && fs.aggr.type.toBasetype().ty == Tstruct && - (cast(TypeStruct)(fs.aggr.type.toBasetype())).sym.dtor && + if (fs.aggr.type && fs.aggr.type.toBasetype().isTypeStruct() && + fs.aggr.type.toBasetype().isTypeStruct().sym.dtor && !fs.aggr.isTypeExp() && !fs.aggr.isLvalue()) { // https://issues.dlang.org/show_bug.cgi?id=14653 @@ -804,9 +804,9 @@ Statement statementSemanticVisit(Statement s, Scope* sc) Parameter fparam = fparameters[0]; if ((fparam.type.ty == Tpointer || fparam.type.ty == Tdelegate) && - fparam.type.nextOf().ty == Tfunction) + fparam.type.nextOf().isTypeFunction()) { - TypeFunction tf = cast(TypeFunction)fparam.type.nextOf(); + auto tf = fparam.type.nextOf().isTypeFunction(); foreachParamCount = tf.parameterList.length; foundMismatch = true; } @@ -1644,8 +1644,8 @@ Statement statementSemanticVisit(Statement s, Scope* sc) } else { - if (ifs.condition.op == EXP.dotIdentifier) - (cast(DotIdExp)ifs.condition).noderef = true; + if (auto dotid = ifs.condition.isDotIdExp()) + dotid.noderef = true; ifs.condition = ifs.condition.expressionSemantic(scd); ifs.condition = resolveProperties(scd, ifs.condition); @@ -1910,8 +1910,8 @@ Statement statementSemanticVisit(Statement s, Scope* sc) while (!ss.condition.isErrorExp()) { // preserve enum type for final switches - if (ss.condition.type.ty == Tenum) - te = cast(TypeEnum)ss.condition.type; + if (auto tenum = ss.condition.type.isTypeEnum()) + te = tenum; if (ss.condition.type.isString()) { // If it's not an array, cast it to one @@ -2222,14 +2222,13 @@ Statement statementSemanticVisit(Statement s, Scope* sc) 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; + while (e.isCastExp()) + e = e.isCastExp().e1; /* This is where variables are allowed as case expressions. */ - if (e.op == EXP.variable) + if (auto ve = e.isVarExp()) { - VarExp ve = cast(VarExp)e; VarDeclaration v = ve.var.isVarDeclaration(); Type t = cs.exp.type.toBasetype(); if (v && (t.isintegral() || t.ty == Tclass)) @@ -3227,9 +3226,9 @@ Statement statementSemanticVisit(Statement s, Scope* sc) sym.parent = sc.scopesym; sym.endlinnum = ws.endloc.linnum; } - else if (ws.exp.op == EXP.type) + else if (auto et = ws.exp.isTypeExp()) { - Dsymbol s = (cast(TypeExp)ws.exp).type.toDsymbol(sc); + Dsymbol s = et.type.toDsymbol(sc); if (!s || !s.isScopeDsymbol()) { error(ws.loc, "`with` type `%s` has no members", ws.exp.toChars()); @@ -3767,16 +3766,15 @@ public bool throwSemantic(const ref Loc loc, ref Expression exp, Scope* sc) if (FuncDeclaration fd = sc.parent.isFuncDeclaration()) fd.hasReturnExp |= 2; - if (exp.op == EXP.new_) + if (auto ne = exp.isNewExp()) { - NewExp ne = cast(NewExp) exp; ne.thrownew = true; } exp = exp.expressionSemantic(sc); exp = resolveProperties(sc, exp); exp = checkGC(sc, exp); - if (exp.op == EXP.error) + if (exp.isErrorExp()) return false; if (!exp.type.isNaked()) { @@ -3805,12 +3803,12 @@ private extern(D) Expression applyOpApply(ForeachStatement fs, Expression flde, { message(loc, "To enforce `@safe`, the compiler allocates a closure unless `opApply()` uses `scope`"); } - (cast(FuncExp)flde).fd.tookAddressOf = 1; + flde.isFuncExp().fd.tookAddressOf = 1; } else { if (sc2.useDIP1000 == FeatureState.enabled) - ++(cast(FuncExp)flde).fd.tookAddressOf; // allocate a closure unless the opApply() uses 'scope' + ++flde.isFuncExp().fd.tookAddressOf; // allocate a closure unless the opApply() uses 'scope' } assert(tab.ty == Tstruct || tab.ty == Tclass); assert(sapply); @@ -3821,7 +3819,7 @@ private extern(D) Expression applyOpApply(ForeachStatement fs, Expression flde, ec = new DotIdExp(fs.loc, fs.aggr, sapply.ident); ec = new CallExp(fs.loc, ec, flde); ec = ec.expressionSemantic(sc2); - if (ec.op == EXP.error) + if (ec.isErrorExp()) return null; if (ec.type != Type.tint32) { @@ -3838,11 +3836,12 @@ private extern(D) Expression applyDelegate(ForeachStatement fs, Expression flde, /* Call: * aggr(flde) */ - if (fs.aggr.op == EXP.delegate_ && (cast(DelegateExp)fs.aggr).func.isNested() && - !(cast(DelegateExp)fs.aggr).func.needThis()) + if (auto de = fs.aggr.isDelegateExp()) + if (de.func.isNested() && + !de.func.needThis()) { // https://issues.dlang.org/show_bug.cgi?id=3560 - fs.aggr = (cast(DelegateExp)fs.aggr).e1; + fs.aggr = de.e1; } ec = new CallExp(fs.loc, fs.aggr, flde); ec = ec.expressionSemantic(sc2); @@ -4099,7 +4098,7 @@ private FuncExp foreachBodyToFunction(Scope* sc, ForeachStatement fs, TypeFuncti fld.tookAddressOf = 0; if (flde.op == EXP.error) return null; - return cast(FuncExp)flde; + return flde.isFuncExp(); } @@ -4273,9 +4272,9 @@ Statement scopeCode(Statement statement, Scope* sc, out Statement sentry, out St { if (auto es = statement.isExpStatement()) { - if (es.exp && es.exp.op == EXP.declaration) + if (es.exp && es.exp.isDeclarationExp()) { - auto de = cast(DeclarationExp)es.exp; + auto de = es.exp.isDeclarationExp(); auto v = de.declaration.isVarDeclaration(); if (v && !v.isDataseg()) { @@ -4401,7 +4400,7 @@ public auto makeTupleForeach(Scope* sc, bool isStatic, bool isDecl, ForeachState } Type tab = fs.aggr.type.toBasetype(); - TypeTuple tuple = cast(TypeTuple)tab; + TypeTuple tuple = tab.isTypeTuple(); Statements* statements; Dsymbols* declarations; @@ -4413,12 +4412,12 @@ public auto makeTupleForeach(Scope* sc, bool isStatic, bool isDecl, ForeachState //printf("aggr: op = %d, %s\n", fs.aggr.op, fs.aggr.toChars()); size_t n; TupleExp te = null; - if (fs.aggr.op == EXP.tuple) // expression tuple + if (auto ate = fs.aggr.isTupleExp()) // expression tuple { - te = cast(TupleExp)fs.aggr; + te = ate; n = te.exps.length; } - else if (fs.aggr.op == EXP.type) // type tuple + else if (fs.aggr.isTypeExp()) // type tuple { n = Parameter.dim(tuple.arguments); } From 0bb347ffcb13c8b26d55f23429111b69892f6e04 Mon Sep 17 00:00:00 2001 From: Martin Kinkelin Date: Fri, 8 Dec 2023 22:18:13 +0100 Subject: [PATCH 115/215] druntime: Merge win64.mak into posix.mak --- runtime/druntime/posix.mak | 106 +++++++++++++++++++++---------------- 1 file changed, 61 insertions(+), 45 deletions(-) diff --git a/runtime/druntime/posix.mak b/runtime/druntime/posix.mak index 3cfc8bff49e..089d9b6d512 100644 --- a/runtime/druntime/posix.mak +++ b/runtime/druntime/posix.mak @@ -11,12 +11,28 @@ TOOLS_DIR=../../tools include $(DMD_DIR)/src/osmodel.mak +ifeq (windows,$(OS)) + DOTEXE:=.exe + DOTDLL:=.dll + DOTLIB:=.lib + DOTOBJ:=.obj +else + DOTEXE:= + DOTDLL:=$(if $(findstring $(OS),osx),.dylib,.so) + DOTLIB:=.a + DOTOBJ:=.o +endif + +ifeq (osx,$(OS)) + export MACOSX_DEPLOYMENT_TARGET=10.9 +endif + # Default to a release built, override with BUILD=debug ifeq (,$(BUILD)) -BUILD_WAS_SPECIFIED=0 -BUILD=release + BUILD_WAS_SPECIFIED=0 + BUILD=release else -BUILD_WAS_SPECIFIED=1 + BUILD_WAS_SPECIFIED=1 endif ifneq ($(BUILD),release) @@ -25,7 +41,7 @@ ifneq ($(BUILD),release) endif endif -DMD=$(DMD_DIR)/../generated/$(OS)/$(BUILD)/$(MODEL)/dmd +DMD=$(DMD_DIR)/../generated/$(OS)/$(BUILD)/$(MODEL)/dmd$(DOTEXE) INSTALL_DIR=../../install # directory where the html files for the documentation are placed @@ -36,22 +52,17 @@ OPTIONAL_COVERAGE:=$(if $(TEST_COVERAGE),-cov=ctfe,) # default to PIC, use PIC=1/0 to en-/disable PIC. # Note that shared libraries and C files are always compiled with PIC. -ifeq ($(PIC),) - PIC:=1 -endif -ifeq ($(PIC),1) - override PIC:=-fPIC -else +ifeq (windows,$(OS)) override PIC:= -endif - -ifeq (osx,$(OS)) - DOTDLL:=.dylib - DOTLIB:=.a - export MACOSX_DEPLOYMENT_TARGET=10.9 else - DOTDLL:=.so - DOTLIB:=.a + ifeq ($(PIC),) + PIC:=1 + endif + ifeq ($(PIC),1) + override PIC:=-fPIC + else + override PIC:= + endif endif # build with shared library support @@ -65,7 +76,7 @@ MAKEFILE = $(firstword $(MAKEFILE_LIST)) DDOCFLAGS=-conf= -c -w -o- -Iimport -version=CoreDdoc # Set CFLAGS -CFLAGS=$(MODEL_FLAG) -fPIC -DHAVE_UNISTD_H +CFLAGS=$(if $(findstring $(OS),windows),,$(MODEL_FLAG) -fPIC -DHAVE_UNISTD_H) ifeq ($(BUILD),debug) CFLAGS += -g else @@ -98,17 +109,16 @@ SHARED=$(if $(findstring $(OS),linux freebsd),1,) ROOT_DIR := $(shell pwd) PHOBOS_DFLAGS=-conf= $(MODEL_FLAG) -I$(ROOT_DIR)/import -I$(PHOBOS_PATH) -L-L$(PHOBOS_PATH)/generated/$(OS)/$(BUILD)/$(MODEL) $(PIC) ifeq (1,$(SHARED)) -PHOBOS_DFLAGS+=-defaultlib=libphobos2.so -L-rpath=$(PHOBOS_PATH)/generated/$(OS)/$(BUILD)/$(MODEL) +PHOBOS_DFLAGS+=-defaultlib=libphobos2$(DOTDLL) -L-rpath=$(PHOBOS_PATH)/generated/$(OS)/$(BUILD)/$(MODEL) endif ROOT_OF_THEM_ALL = ../generated ROOT = $(ROOT_OF_THEM_ALL)/$(OS)/$(BUILD)/$(MODEL) OBJDIR=obj/$(OS)/$(BUILD)/$(MODEL) -DRUNTIME_BASE=druntime-$(OS)$(MODEL) -DRUNTIME=$(ROOT)/libdruntime.a -DRUNTIMESO=$(ROOT)/libdruntime.so -DRUNTIMESOOBJ=$(ROOT)/libdruntime.so.o -DRUNTIMESOLIB=$(ROOT)/libdruntime.so.a +DRUNTIME=$(ROOT)/$(if $(findstring $(OS),windows),,lib)druntime$(DOTLIB) +DRUNTIMESO=$(ROOT)/$(if $(findstring $(OS),windows),,lib)druntime$(DOTDLL) +DRUNTIMESOOBJ=$(DRUNTIMESO)$(DOTOBJ) +DRUNTIMESOLIB=$(DRUNTIMESO)$(DOTLIB) STDDOC= @@ -123,10 +133,6 @@ SRCS:=$(subst \,/,$(SRCS)) # NOTE: trace.d and cover.d are not necessary for a successful build # as both are used for debugging features (profiling and coverage) -# NOTE: a pre-compiled minit.obj has been provided in dmd for Win32 and -# minit.asm is not used by dmd for Linux - -OBJS= $(ROOT)/errno_c.o $(ROOT)/threadasm.o $(ROOT)/valgrind.o # use timelimit to avoid deadlocks if available TIMELIMIT:=$(if $(shell which timelimit 2>/dev/null || true),timelimit -t 10 ,) @@ -352,7 +358,7 @@ $(IMPDIR)/%.h : src/%.h ######################## Build DMD if non-existent ############################## -$(DMD_DIR)/../generated/$(OS)/$(BUILD)/$(MODEL)/dmd: +$(DMD_DIR)/../generated/$(OS)/$(BUILD)/$(MODEL)/dmd$(DOTEXE): $(MAKE) -C $(DMD_DIR)/.. dmd BUILD=$(BUILD) OS=$(OS) MODEL=$(MODEL) DMD="" # alias using the absolute path (the Phobos Makefile specifies an absolute path) @@ -360,32 +366,41 @@ $(abspath $(DMD_DIR)/../generated/$(OS)/$(BUILD)/$(MODEL)/dmd): $(DMD_DIR)/../ge ################### C/ASM Targets ############################ -$(ROOT)/%.o : src/rt/%.c $(DMD) +# Although dmd is compiling the .c files, the preprocessor used on Windows is cl.exe. +# The INCLUDE environment variable needs to be set with the path to the VC system include files. + +# NOTE: minit.asm is only used for -m32omf on Windows +OBJS:=$(ROOT)/errno_c$(DOTOBJ) +ifneq (windows,$(OS)) + OBJS+=$(ROOT)/threadasm$(DOTOBJ) $(ROOT)/valgrind$(DOTOBJ) +endif + +$(ROOT)/%$(DOTOBJ) : src/rt/%.c $(DMD) @mkdir -p $(dir $@) $(DMD) -c $(DFLAGS) -I. $< -of$@ -$(ROOT)/errno_c.o : src/core/stdc/errno.c $(DMD) +$(ROOT)/errno_c$(DOTOBJ) : src/core/stdc/errno.c $(DMD) @mkdir -p $(dir $@) - $(DMD) -c $(DFLAGS) -I. $< -of$@ + $(DMD) -c $(DFLAGS) -I. -P=-I. $< -of$@ -$(ROOT)/threadasm.o : src/core/threadasm.S +$(ROOT)/threadasm$(DOTOBJ) : src/core/threadasm.S @mkdir -p $(dir $@) $(CC) -c $(CFLAGS) $< -o$@ -$(ROOT)/valgrind.o : src/etc/valgrind/valgrind.c src/etc/valgrind/valgrind.h src/etc/valgrind/memcheck.h +$(ROOT)/valgrind$(DOTOBJ) : src/etc/valgrind/valgrind.c src/etc/valgrind/valgrind.h src/etc/valgrind/memcheck.h @mkdir -p `dirname $@` $(CC) -c $(CFLAGS) $< -o$@ ######################## Create a shared library ############################## -$(DRUNTIMESO) $(DRUNTIMESOLIB) dll: DFLAGS+=-version=Shared -fPIC +$(DRUNTIMESO) $(DRUNTIMESOLIB) dll: DFLAGS+=-version=Shared $(if $(findstring $(OS),windows),,-fPIC) dll: $(DRUNTIMESOLIB) $(DRUNTIMESO): $(OBJS) $(SRCS) $(DMD) $(DMD) -shared -debuglib= -defaultlib= -of$(DRUNTIMESO) $(DFLAGS) $(SRCS) $(OBJS) $(LINKDL) -L-lpthread -L-lm $(DRUNTIMESOLIB): $(OBJS) $(SRCS) $(DMD) - $(DMD) -c -fPIC -of$(DRUNTIMESOOBJ) $(DFLAGS) $(SRCS) + $(DMD) -c $(if $(findstring $(OS),windows),,-fPIC) -of$(DRUNTIMESOOBJ) $(DFLAGS) $(SRCS) $(DMD) -conf= -lib -of$(DRUNTIMESOLIB) $(DRUNTIMESOOBJ) $(OBJS) ################### Library generation ######################### @@ -396,7 +411,8 @@ $(DRUNTIME): $(OBJS) $(SRCS) $(DMD) lib: $(DRUNTIME) UT_MODULES:=$(patsubst src/%.d,$(ROOT)/unittest/%,$(SRCS)) -HAS_ADDITIONAL_TESTS:=$(shell test -d test && echo 1) +# TODO: Windows +HAS_ADDITIONAL_TESTS:=$(if $(findstring $(OS),windows),,$(shell test -d test && echo 1)) ifeq ($(HAS_ADDITIONAL_TESTS),1) ADDITIONAL_TESTS:=test/init_fini test/exceptions test/coverage test/profile test/cycles test/allocations test/typeinfo \ test/aa test/cpuid test/gc test/hash test/lifetime \ @@ -428,19 +444,19 @@ $(addprefix $(ROOT)/unittest/,$(DISABLED_TESTS)) : ifeq (,$(SHARED)) -$(ROOT)/unittest/test_runner: $(OBJS) $(SRCS) src/test_runner.d $(DMD) - $(DMD) $(UDFLAGS) $(UTFLAGS) -of$@ src/test_runner.d $(SRCS) $(OBJS) -debuglib= -defaultlib= -L-lpthread -L-lm +$(ROOT)/unittest/test_runner$(DOTEXE): $(OBJS) $(SRCS) src/test_runner.d $(DMD) + $(DMD) $(UDFLAGS) $(UTFLAGS) -of$@ src/test_runner.d $(SRCS) $(OBJS) -defaultlib= $(if $(findstring $(OS),windows),user32.lib,-L-lpthread -L-lm) else UT_DRUNTIME:=$(ROOT)/unittest/libdruntime-ut$(DOTDLL) -$(UT_DRUNTIME): UDFLAGS+=-version=Shared -fPIC +$(UT_DRUNTIME): UDFLAGS+=-version=Shared $(if $(findstring $(OS),windows),,-fPIC) $(UT_DRUNTIME): $(OBJS) $(SRCS) $(DMD) - $(DMD) $(UDFLAGS) -shared $(UTFLAGS) -of$@ $(SRCS) $(OBJS) $(LINKDL) -debuglib= -defaultlib= -L-lpthread -L-lm + $(DMD) $(UDFLAGS) -shared $(UTFLAGS) -of$@ $(SRCS) $(OBJS) $(LINKDL) -defaultlib= $(if $(findstring $(OS),windows),user32.lib,-L-lpthread -L-lm) -$(ROOT)/unittest/test_runner: $(UT_DRUNTIME) src/test_runner.d $(DMD) - $(DMD) $(UDFLAGS) -of$@ src/test_runner.d -L$(UT_DRUNTIME) -debuglib= -defaultlib= -L-lpthread -L-lm +$(ROOT)/unittest/test_runner$(DOTEXE): $(UT_DRUNTIME) src/test_runner.d $(DMD) + $(DMD) $(UDFLAGS) -of$@ src/test_runner.d -L$(UT_DRUNTIME) -defaultlib= $(if $(findstring $(OS),windows),user32.lib,-L-lpthread -L-lm) endif @@ -450,7 +466,7 @@ BETTERCTESTS_DIR=$(ROOT)/betterctests # macro that returns the module name given the src path moduleName=$(subst rt.invariant,invariant,$(subst object_,object,$(subst /,.,$(1)))) -$(ROOT)/unittest/% : $(ROOT)/unittest/test_runner +$(ROOT)/unittest/% : $(ROOT)/unittest/test_runner$(DOTEXE) @mkdir -p $(dir $@) # make the file very old so it builds and runs again if it fails @touch -t 197001230123 $@ From 1b6c9bd9d649bb5306904201248dc75e1939ba4d Mon Sep 17 00:00:00 2001 From: Martin Kinkelin Date: Fri, 8 Dec 2023 23:56:15 +0100 Subject: [PATCH 116/215] Azure CI: Switch to GNU make for building druntime on Windows --- runtime/druntime/win64.mak | 73 +------------------------------------- 1 file changed, 1 insertion(+), 72 deletions(-) diff --git a/runtime/druntime/win64.mak b/runtime/druntime/win64.mak index ea4f76b02e7..658a6a3eafc 100644 --- a/runtime/druntime/win64.mak +++ b/runtime/druntime/win64.mak @@ -5,10 +5,6 @@ # Set to `32mscoff` for a 32-bit build, `64` for 64-bit build. MODEL=64 -# Assume MSVC cl.exe in PATH is set up for the target MODEL. -# Otherwise set it explicitly, e.g., to `C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Tools\MSVC\14.29.30133\bin\Hostx86\x86\cl.exe`. -CC=cl - DMD_DIR=..\compiler BUILD=release @@ -17,61 +13,11 @@ OS=windows # The D compiler used to build things DMD=$(DMD_DIR)\..\generated\$(OS)\$(BUILD)\$(MODEL)\dmd -DOCDIR=doc -IMPDIR=import - # Make program to use. Designed to be run with make.exe which can be obtained from # https://downloads.dlang.org/other/dm857c.zip MAKE=make -HOST_DMD=dmd - -DFLAGS=-m$(MODEL) -conf= -O -release -preview=dip1000 -preview=fieldwise -preview=dtorfields -inline -w -Isrc -Iimport -UDFLAGS=-m$(MODEL) -conf= -O -release -preview=dip1000 -preview=fieldwise -w -version=_MSC_VER_$(_MSC_VER) -Isrc -Iimport - -UTFLAGS=-version=CoreUnittest -unittest -checkaction=context - -DRUNTIME_BASE=druntime$(MODEL) -DRUNTIME=lib\$(DRUNTIME_BASE).lib - -DOCFMT= - -target: copy $(DRUNTIME) - -$(mak\COPY) -$(mak\DOCS) -$(mak\SRCS) - -# NOTE: trace.d and cover.d are not necessary for a successful build -# as both are used for debugging features (profiling and coverage) - -OBJS= errno_c_$(MODEL).obj -OBJS_TO_DELETE= errno_c_$(MODEL).obj - -######################## Header file copy ############################## - -import: copy - -copy: - "$(MAKE)" -f mak/WINDOWS copy DMD="$(DMD)" HOST_DMD="$(HOST_DMD)" MODEL=$(MODEL) IMPDIR="$(IMPDIR)" - -################### C\ASM Targets ############################ - -# Although dmd is compiling the .c files, the preprocessor used is cl.exe. The INCLUDE -# environment variable needs to be set with the path to the VC system include files. - -errno_c_$(MODEL).obj: src\core\stdc\errno.c - $(DMD) -c -of=$@ $(DFLAGS) -P=-I. src\core\stdc\errno.c - -################### Library generation ######################### - -$(DRUNTIME): $(OBJS) $(SRCS) win64.mak - *"$(DMD)" -lib -of$(DRUNTIME) -Xfdruntime.json $(DFLAGS) $(SRCS) $(OBJS) - -# due to -conf= on the command line, LINKCMD and LIB need to be set in the environment -unittest: $(SRCS) $(DRUNTIME) - *"$(DMD)" $(UDFLAGS) -version=druntime_unittest $(UTFLAGS) -ofunittest.exe -main $(SRCS) $(DRUNTIME) -debuglib=$(DRUNTIME) -defaultlib=$(DRUNTIME) user32.lib - .\unittest.exe +DRUNTIME=$(DMD_DIR)\..\generated\$(OS)\$(BUILD)\$(MODEL)\druntime.lib ################### tests ###################################### @@ -117,20 +63,3 @@ test_common: test_shared test_aa test_allocations test_cpuid test_exceptions tes test_mingw: test_common test_betterc_mingw test_all: test_common test_betterc test_uuid test_stdcpp - -################### zip/install/clean ########################## - -zip: druntime.zip - -druntime.zip: import - del druntime.zip - git ls-tree --name-only -r HEAD >MANIFEST.tmp - zip32 -T -ur druntime @MANIFEST.tmp - del MANIFEST.tmp - -install: druntime.zip - unzip -o druntime.zip -d \dmd2\src\druntime - -clean: - del $(DRUNTIME) $(OBJS_TO_DELETE) - rmdir /S /Q $(DOCDIR) $(IMPDIR) From e255e37c470dbeab574c13e66395c97406ba8b59 Mon Sep 17 00:00:00 2001 From: Martin Kinkelin Date: Sat, 9 Dec 2023 02:20:05 +0100 Subject: [PATCH 117/215] druntime: Merge win32.mak into posix.mak --- runtime/druntime/posix.mak | 11 +++- runtime/druntime/win32.mak | 123 +------------------------------------ 2 files changed, 10 insertions(+), 124 deletions(-) diff --git a/runtime/druntime/posix.mak b/runtime/druntime/posix.mak index 089d9b6d512..749f8eca5b4 100644 --- a/runtime/druntime/posix.mak +++ b/runtime/druntime/posix.mak @@ -369,9 +369,11 @@ $(abspath $(DMD_DIR)/../generated/$(OS)/$(BUILD)/$(MODEL)/dmd): $(DMD_DIR)/../ge # Although dmd is compiling the .c files, the preprocessor used on Windows is cl.exe. # The INCLUDE environment variable needs to be set with the path to the VC system include files. -# NOTE: minit.asm is only used for -m32omf on Windows OBJS:=$(ROOT)/errno_c$(DOTOBJ) -ifneq (windows,$(OS)) +ifeq (32omf,$(MODEL)) + # minit.asm is only used for -m32omf on Windows; there's a pre-built minit.obj + OBJS+=src/rt/minit$(DOTOBJ) +else ifneq (windows,$(OS)) OBJS+=$(ROOT)/threadasm$(DOTOBJ) $(ROOT)/valgrind$(DOTOBJ) endif @@ -423,7 +425,12 @@ endif .PHONY : unittest ifeq (1,$(BUILD_WAS_SPECIFIED)) +ifeq (32omf,$(MODEL)) +unittest : $(addsuffix /.run,$(ADDITIONAL_TESTS)) + @echo "Skipping druntime unittests because they cannot be linked on Win32 + OMF due to OPTLINK issues." +else unittest : $(UT_MODULES) $(addsuffix /.run,$(ADDITIONAL_TESTS)) +endif else unittest : unittest-debug unittest-release unittest-%: target diff --git a/runtime/druntime/win32.mak b/runtime/druntime/win32.mak index 5e9ffa66e2d..37b96e33ac6 100644 --- a/runtime/druntime/win32.mak +++ b/runtime/druntime/win32.mak @@ -13,112 +13,8 @@ DMD=$(DMD_DIR)\..\generated\$(OS)\$(BUILD)\32\dmd CC=dmc MAKE=make -HOST_DMD=dmd -DOCDIR=doc -IMPDIR=import - -# For compiling D and ImportC files -DFLAGS=-m32omf -conf= -O -release -preview=dip1000 -preview=fieldwise -preview=dtorfields -inline -w -Isrc -Iimport -# For unittest build -UDFLAGS=-m32omf -conf= -O -release -preview=dip1000 -preview=fieldwise -w -Isrc -Iimport -# Also for unittest build -UTFLAGS=-version=CoreUnittest -unittest -checkaction=context - -CFLAGS= - -DRUNTIME_BASE=druntime -DRUNTIME=lib\$(DRUNTIME_BASE).lib - -DOCFMT= - -target: copy $(DRUNTIME) - -$(mak\COPY) -$(mak\DOCS) -$(mak\SRCS) - -# NOTE: trace.d and cover.d are not necessary for a successful build -# as both are used for debugging features (profiling and coverage) -# NOTE: a pre-compiled minit.obj has been provided in dmd for Win32 and -# minit.asm is not used by dmd for Linux - -OBJS= errno_c_32omf.obj src\rt\minit.obj -OBJS_TO_DELETE= errno_c_32omf.obj - -######################## Header file copy ############################## - -import: copy - -copy: - "$(MAKE)" -f mak/WINDOWS copy DMD="$(DMD)" HOST_DMD="$(HOST_DMD)" MODEL=32 IMPDIR="$(IMPDIR)" - -################### Win32 Import Libraries ################### - -IMPLIBS= \ - lib\win32\glu32.lib \ - lib\win32\odbc32.lib \ - lib\win32\opengl32.lib \ - lib\win32\rpcrt4.lib \ - lib\win32\shell32.lib \ - lib\win32\version.lib \ - lib\win32\wininet.lib \ - lib\win32\winspool.lib - -implibsdir: - if not exist lib\win32 mkdir lib\win32 - -implibs: implibsdir $(IMPLIBS) - -lib\win32\glu32.lib: def\glu32.def - implib $@ $** - -lib\win32\odbc32.lib: def\odbc32.def - implib $@ $** - -lib\win32\opengl32.lib: def\opengl32.def - implib $@ $** - -lib\win32\rpcrt4.lib: def\rpcrt4.def - implib $@ $** - -lib\win32\shell32.lib: def\shell32.def - implib $@ $** - -lib\win32\version.lib: def\version.def - implib $@ $** - -lib\win32\wininet.lib: def\wininet.def - implib $@ $** - -lib\win32\winspool.lib: def\winspool.def - implib $@ $** - -################### C\ASM Targets ############################ - -errno_c_32omf.obj: src\core\stdc\errno.c - $(DMD) -c -of=$@ $(DFLAGS) -v -P=-I. src\core\stdc\errno.c - -# only rebuild explicitly -rebuild_minit_obj: src\rt\minit.asm - $(CC) -c $(CFLAGS) src\rt\minit.asm - -################### Library generation ######################### - -$(DRUNTIME): $(OBJS) $(SRCS) win32.mak - *$(DMD) -lib -of$(DRUNTIME) -Xfdruntime.json $(DFLAGS) $(SRCS) $(OBJS) - -################### Unittests ######################### -# Unittest are not run because OPTLINK tends to crash when linking -# unittest.exe. Note that the unittests are still run for -m32mscoff -# and -m64 which are configured in win64.mak - -unittest: unittest.obj - @echo "Unittests cannot be linked on Win32 + OMF due to OPTLINK issues" - -# Split compilation into a different step to avoid unnecessary rebuilds -unittest.obj: $(SRCS) win32.mak - *$(DMD) $(UDFLAGS) $(UTFLAGS) -c -of$@ $(SRCS) +DRUNTIME=$(DMD_DIR)\..\generated\$(OS)\$(BUILD)\32omf\druntime.lib ################### tests ###################################### @@ -147,20 +43,3 @@ test_shared: $(MAKE) -f test\shared\win64.mak "DMD=$(DMD)" MODEL=32omf "VCDIR=$(VCDIR)" DRUNTIMELIB=$(DRUNTIME) "CC=$(CC)" test test_all: test_aa test_allocations test_cpuid test_exceptions test_hash test_gc custom_gc test_shared - -################### zip/install/clean ########################## - -zip: druntime.zip - -druntime.zip: - del druntime.zip - git ls-tree --name-only -r HEAD >MANIFEST.tmp - zip32 -T -ur druntime @MANIFEST.tmp - del MANIFEST.tmp - -install: druntime.zip - unzip -o druntime.zip -d \dmd2\src\druntime - -clean: - del $(DRUNTIME) $(OBJS_TO_DELETE) - rmdir /S /Q $(DOCDIR) $(IMPDIR) From 06ceede888f1ce7b8ddfb29aad4c35bbe92747c5 Mon Sep 17 00:00:00 2001 From: Martin Kinkelin Date: Sat, 9 Dec 2023 03:33:39 +0100 Subject: [PATCH 118/215] druntime: Rename posix.mak to Makefile --- runtime/druntime/{posix.mak => Makefile} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename runtime/druntime/{posix.mak => Makefile} (100%) diff --git a/runtime/druntime/posix.mak b/runtime/druntime/Makefile similarity index 100% rename from runtime/druntime/posix.mak rename to runtime/druntime/Makefile From bb9ad1d0c1690763307079f93c0061519070df4e Mon Sep 17 00:00:00 2001 From: Martin Kinkelin Date: Sat, 9 Dec 2023 03:49:38 +0100 Subject: [PATCH 119/215] druntime: Restore posix.mak, forwarding to generic Makefile --- runtime/druntime/posix.mak | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 runtime/druntime/posix.mak diff --git a/runtime/druntime/posix.mak b/runtime/druntime/posix.mak new file mode 100644 index 00000000000..062a7c12e7b --- /dev/null +++ b/runtime/druntime/posix.mak @@ -0,0 +1,11 @@ +$(warning ===== DEPRECATION NOTICE ===== ) +$(warning ===== DEPRECATION: posix.mak is deprecated. Please use generic Makefile instead.) +$(warning ============================== ) + +# forward everything to Makefile + +target: + $(MAKE) -f Makefile $@ + +%: + $(MAKE) -f Makefile $@ From b4fbd1a1da467581cf9077a6ecd9dd3aac96a2cc Mon Sep 17 00:00:00 2001 From: Martin Kinkelin Date: Sat, 9 Dec 2023 05:40:15 +0100 Subject: [PATCH 120/215] druntime: Fix a few missing .exe in Makefile And get rid of a redundant rule. --- runtime/druntime/Makefile | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/runtime/druntime/Makefile b/runtime/druntime/Makefile index 749f8eca5b4..742da435810 100644 --- a/runtime/druntime/Makefile +++ b/runtime/druntime/Makefile @@ -340,10 +340,6 @@ import: copy copy: $(COPY) -$(IMPDIR)/object.d : src/object.d - @mkdir -p $(dir $@) - @cp $< $@ - $(IMPDIR)/%.di : src/%.di @mkdir -p $(dir $@) @cp $< $@ @@ -367,7 +363,8 @@ $(abspath $(DMD_DIR)/../generated/$(OS)/$(BUILD)/$(MODEL)/dmd): $(DMD_DIR)/../ge ################### C/ASM Targets ############################ # Although dmd is compiling the .c files, the preprocessor used on Windows is cl.exe. -# The INCLUDE environment variable needs to be set with the path to the VC system include files. +# Until https://issues.dlang.org/show_bug.cgi?id=24111 is fixed, the INCLUDE +# enviroment variable needs to be set with the path to the VC system include files. OBJS:=$(ROOT)/errno_c$(DOTOBJ) ifeq (32omf,$(MODEL)) @@ -467,7 +464,7 @@ $(ROOT)/unittest/test_runner$(DOTEXE): $(UT_DRUNTIME) src/test_runner.d $(DMD) endif -TESTS_EXTRACTOR=$(ROOT)/tests_extractor +TESTS_EXTRACTOR=$(ROOT)/tests_extractor$(DOTEXE) BETTERCTESTS_DIR=$(ROOT)/betterctests # macro that returns the module name given the src path @@ -492,13 +489,13 @@ test/%/.run: test/%/Makefile $(DMD) #################### benchmark suite ########################## -$(ROOT)/benchmark: benchmark/runbench.d target $(DMD) +$(ROOT)/benchmark$(DOTEXE): benchmark/runbench.d target $(DMD) $(DMD) $(PHOBOS_DFLAGS) -de $< -of$@ -benchmark: $(ROOT)/benchmark +benchmark: $(ROOT)/benchmark$(DOTEXE) DMD=$(DMD) $< -benchmark-compile-only: $(ROOT)/benchmark $(DMD) +benchmark-compile-only: $(ROOT)/benchmark$(DOTEXE) $(DMD) DMD=$(DMD) $< --repeat=0 --dflags="$(PHOBOS_DFLAGS) -de" #################### test for undesired white spaces ########################## @@ -556,7 +553,7 @@ test/%/.clean: test/%/Makefile $(TESTS_EXTRACTOR): $(TOOLS_DIR)/tests_extractor.d | $(LIB) $(DUB) build --force --single $< - mv $(TOOLS_DIR)/tests_extractor $@ + mv $(TOOLS_DIR)/tests_extractor$(DOTEXE) $@ test_extractor: $(TESTS_EXTRACTOR) From 825863feaa0e437351c32c162ca7c71924b32cc8 Mon Sep 17 00:00:00 2001 From: Martin Kinkelin Date: Sat, 9 Dec 2023 18:43:13 +0100 Subject: [PATCH 121/215] druntime: Make most *test* Makefiles usable on Windows too Still to do: `test/{shared,stdcpp}`. --- dmd/osmodel.mak | 5 +- runtime/druntime/Makefile | 16 ++-- runtime/druntime/test/aa/Makefile | 4 +- runtime/druntime/test/allocations/Makefile | 10 +-- runtime/druntime/test/allocations/win64.mak | 12 --- runtime/druntime/test/betterc/Makefile | 16 +++- runtime/druntime/test/betterc/win64.mak | 50 ------------ runtime/druntime/test/common.mak | 46 +++++++---- runtime/druntime/test/config/Makefile | 10 +-- runtime/druntime/test/coverage/Makefile | 36 ++++++--- runtime/druntime/test/cpuid/Makefile | 4 +- runtime/druntime/test/cpuid/win64.mak | 12 --- runtime/druntime/test/cycles/Makefile | 8 +- runtime/druntime/test/exceptions/Makefile | 68 ++++++++-------- runtime/druntime/test/exceptions/win64.mak | 10 --- runtime/druntime/test/gc/Makefile | 77 ++++++++++--------- runtime/druntime/test/gc/win64.mak | 58 -------------- runtime/druntime/test/hash/Makefile | 4 +- runtime/druntime/test/imports/Makefile | 2 +- runtime/druntime/test/init_fini/Makefile | 4 +- runtime/druntime/test/init_fini/win64.mak | 12 --- runtime/druntime/test/lifetime/Makefile | 4 +- runtime/druntime/test/profile/Makefile | 21 +++-- .../profile/myprofilegc.log.windows.32.exp | 21 +++++ .../profile/myprofilegc.log.windows.64.exp | 21 +++++ runtime/druntime/test/shared/Makefile | 2 +- runtime/druntime/test/thread/Makefile | 21 +++-- runtime/druntime/test/traits/Makefile | 4 +- runtime/druntime/test/typeinfo/Makefile | 4 +- runtime/druntime/test/unittest/Makefile | 3 +- runtime/druntime/test/uuid/Makefile | 23 ++++++ runtime/druntime/test/uuid/win64.mak | 9 --- runtime/druntime/test/valgrind/Makefile | 16 ++-- runtime/druntime/win32.mak | 45 ----------- runtime/druntime/win64.mak | 65 ---------------- 35 files changed, 296 insertions(+), 427 deletions(-) delete mode 100644 runtime/druntime/test/allocations/win64.mak delete mode 100644 runtime/druntime/test/betterc/win64.mak delete mode 100644 runtime/druntime/test/cpuid/win64.mak delete mode 100644 runtime/druntime/test/exceptions/win64.mak delete mode 100644 runtime/druntime/test/gc/win64.mak delete mode 100644 runtime/druntime/test/init_fini/win64.mak create mode 100644 runtime/druntime/test/profile/myprofilegc.log.windows.32.exp create mode 100644 runtime/druntime/test/profile/myprofilegc.log.windows.64.exp create mode 100644 runtime/druntime/test/uuid/Makefile delete mode 100644 runtime/druntime/test/uuid/win64.mak delete mode 100644 runtime/druntime/win32.mak delete mode 100644 runtime/druntime/win64.mak diff --git a/dmd/osmodel.mak b/dmd/osmodel.mak index 3c507e43aca..69676c18b00 100644 --- a/dmd/osmodel.mak +++ b/dmd/osmodel.mak @@ -61,7 +61,10 @@ endif ifeq (windows,$(OS)) # Note: setting SHELL to an absolute path to bash.exe does NOT suffice. # The GNU tools like {rm,cp,mkdir}.exe need to be in PATH. - export PATH:=C:\Program Files\Git\usr\bin;$(PATH) + ifeq (,$(findstring C:\Program Files\Git\usr\bin,$(PATH))) + export PATH:=C:\Program Files\Git\usr\bin;$(PATH) + endif + # setting SHELL is very special on Windows: https://www.gnu.org/software/make/manual/html_node/Choosing-the-Shell.html#Choosing-a-Shell-in-DOS-and-Windows SHELL=bash.exe $(info Using make SHELL "$(SHELL)", should be bash.) endif diff --git a/runtime/druntime/Makefile b/runtime/druntime/Makefile index 742da435810..7feb67a2ffb 100644 --- a/runtime/druntime/Makefile +++ b/runtime/druntime/Makefile @@ -410,14 +410,16 @@ $(DRUNTIME): $(OBJS) $(SRCS) $(DMD) lib: $(DRUNTIME) UT_MODULES:=$(patsubst src/%.d,$(ROOT)/unittest/%,$(SRCS)) -# TODO: Windows -HAS_ADDITIONAL_TESTS:=$(if $(findstring $(OS),windows),,$(shell test -d test && echo 1)) +HAS_ADDITIONAL_TESTS:=$(shell test -d test && echo 1) ifeq ($(HAS_ADDITIONAL_TESTS),1) - ADDITIONAL_TESTS:=test/init_fini test/exceptions test/coverage test/profile test/cycles test/allocations test/typeinfo \ - test/aa test/cpuid test/gc test/hash test/lifetime \ - test/thread test/unittest test/imports test/betterc test/stdcpp test/config \ - test/traits test/valgrind - ADDITIONAL_TESTS+=$(if $(SHARED),test/shared,) + ADDITIONAL_TESTS:=test/init_fini test/exceptions test/coverage test/profile test/cycles test/allocations test/typeinfo \ + test/aa test/cpuid test/gc test/hash test/lifetime \ + test/thread test/unittest test/imports test/betterc test/config \ + test/traits test/uuid test/valgrind + ifneq (windows,$(OS)) # FIXME + ADDITIONAL_TESTS+=test/stdcpp + endif + ADDITIONAL_TESTS+=$(if $(SHARED),test/shared,) endif .PHONY : unittest diff --git a/runtime/druntime/test/aa/Makefile b/runtime/druntime/test/aa/Makefile index 8d31593adc2..839237a9292 100644 --- a/runtime/druntime/test/aa/Makefile +++ b/runtime/druntime/test/aa/Makefile @@ -5,12 +5,12 @@ TESTS:=test_aa .PHONY: all clean all: $(addprefix $(ROOT)/,$(addsuffix .done,$(TESTS))) -$(ROOT)/test_aa.done: $(ROOT)/%.done : $(ROOT)/% +$(ROOT)/%.done: $(ROOT)/%$(DOTEXE) @echo Testing $* $(QUIET)$(TIMELIMIT)$(ROOT)/$* $(RUN_ARGS) @touch $@ -$(ROOT)/%: $(SRC)/%.d +$(ROOT)/%$(DOTEXE): $(SRC)/%.d $(QUIET)$(DMD) $(DFLAGS) -of$@ $< clean: diff --git a/runtime/druntime/test/allocations/Makefile b/runtime/druntime/test/allocations/Makefile index db8494a4814..99936bf1482 100644 --- a/runtime/druntime/test/allocations/Makefile +++ b/runtime/druntime/test/allocations/Makefile @@ -8,20 +8,20 @@ SED:=sed .PHONY: all clean all: $(addprefix $(ROOT)/,$(addsuffix .done,$(TESTS))) -$(ROOT)/alloc_from_assert.done: $(ROOT)/alloc_from_assert +$(ROOT)/alloc_from_assert.done: $(ROOT)/alloc_from_assert$(DOTEXE) @echo Testing $* $(QUIET)$(TIMELIMIT)$(ROOT)/alloc_from_assert $(RUN_ARGS) @touch $@ $(ROOT)/overflow_from_zero.done: STDERR_EXP="Memory allocation failed" $(ROOT)/overflow_from_existing.done: STDERR_EXP="Memory allocation failed" -$(ROOT)/%.done: $(ROOT)/% +$(ROOT)/%.done: $(ROOT)/%$(DOTEXE) @echo Testing $* - $(NEGATE) $(QUIET)$(TIMELIMIT)$(ROOT)/$* $(RUN_ARGS) 2>&1 1>/dev/null | head -n 1 | grep -qF $(STDERR_EXP) + $(NEGATE) $(QUIET)$(TIMELIMIT)$(ROOT)/$* $(RUN_ARGS) 2>&1 1>/dev/null | head -n 2 | grep -qF $(STDERR_EXP) @touch $@ -$(ROOT)/unittest_assert: DFLAGS+=-unittest -version=CoreUnittest -$(ROOT)/%: $(SRC)/%.d +$(ROOT)/unittest_assert$(DOTEXE): DFLAGS+=-unittest -version=CoreUnittest +$(ROOT)/%$(DOTEXE): $(SRC)/%.d $(QUIET)$(DMD) $(DFLAGS) -of$@ $< clean: diff --git a/runtime/druntime/test/allocations/win64.mak b/runtime/druntime/test/allocations/win64.mak deleted file mode 100644 index 97dd5267abe..00000000000 --- a/runtime/druntime/test/allocations/win64.mak +++ /dev/null @@ -1,12 +0,0 @@ -# built from the druntime top-level folder -# to be overwritten by caller -DMD=dmd -MODEL=64 -DRUNTIMELIB=druntime64.lib - -test: alloc_from_assert - -alloc_from_assert: - $(DMD) -m$(MODEL) -conf= -Iimport -defaultlib=$(DRUNTIMELIB) test\allocations\src\$@.d - $@.exe - del $@.* diff --git a/runtime/druntime/test/betterc/Makefile b/runtime/druntime/test/betterc/Makefile index 53d90c1fa08..2b5b32b2fdb 100644 --- a/runtime/druntime/test/betterc/Makefile +++ b/runtime/druntime/test/betterc/Makefile @@ -3,15 +3,23 @@ include ../common.mak TESTS:=test18828 test19416 test19421 test19561 test20088 test20613 test19924 test22336 test19933 .PHONY: all clean -all: $(addprefix $(ROOT)/,$(addsuffix ,$(TESTS))) $(addprefix $(ROOT)/,test19924.done) +all: $(addprefix $(ROOT)/,$(addsuffix .done,$(TESTS))) -$(ROOT)/test19924.done: $(ROOT)/%.done : $(ROOT)/% +$(ROOT)/%.done: $(ROOT)/%$(DOTEXE) @echo Running $* $(QUIET)$(TIMELIMIT)$(ROOT)/$* $(RUN_ARGS) @touch $@ -$(ROOT)/%: $(SRC)/%.d - $(QUIET)$(DMD) -betterC -of$@ $< +# for the Windows MinGW CI job: +ifneq (,$(findstring -mscrtlib=msvcrt120,$(DFLAGS))) +# DFLAGS=-mscrtlib=msvcrt120 takes precedence over any command line flags, so +# specify vcruntime140.lib explicitly for using mingw with Universal CRT. +$(ROOT)/test19933$(DOTEXE): $(SRC)/test19933.d + $(QUIET)$(DMD) $(MODEL_FLAG) -I../../src -betterC -of$@ $< -Lvcruntime140.lib -Llegacy_stdio_definitions.lib -L/NODEFAULTLIB:msvcrt120.lib +endif + +$(ROOT)/%$(DOTEXE): $(SRC)/%.d + $(QUIET)$(DMD) $(MODEL_FLAG) -I../../src -betterC -of$@ $< clean: rm -rf $(ROOT) diff --git a/runtime/druntime/test/betterc/win64.mak b/runtime/druntime/test/betterc/win64.mak deleted file mode 100644 index 0e060b54800..00000000000 --- a/runtime/druntime/test/betterc/win64.mak +++ /dev/null @@ -1,50 +0,0 @@ -# built from the druntime top-level folder -# to be overwritten by caller -DMD=dmd -MODEL=64 - -TESTS=test18828 test19416 test19421 test19561 test20088 test20613 test19924 test22336 test19933$(MINGW) - -test: $(TESTS) - -test18828: - $(DMD) -m$(MODEL) -conf= -Iimport -betterC -run test\betterc\src\$@.d - del $@.* - -test19416: - $(DMD) -m$(MODEL) -conf= -Iimport -betterC -run test\betterc\src\$@.d - del $@.* - -test19421: - $(DMD) -m$(MODEL) -conf= -Iimport -betterC -run test\betterc\src\$@.d - del $@.* - -test19561: - $(DMD) -m$(MODEL) -conf= -Iimport -betterC -run test\betterc\src\$@.d - del $@.* - -test20088: - $(DMD) -m$(MODEL) -conf= -Iimport -betterC -run test\betterc\src\$@.d - del $@.* - -test20613: - $(DMD) -m$(MODEL) -conf= -Iimport -betterC -run test\betterc\src\$@.d - del $@.* - -test19924: - $(DMD) -m$(MODEL) -conf= -Iimport -betterC -run test\betterc\src\$@.d - del $@.* - -test22336: - $(DMD) -m$(MODEL) -conf= -Iimport -betterC -run test\betterc\src\$@.d - del $@.* - -test19933: - $(DMD) -m$(MODEL) -conf= -Iimport -betterC -run test\betterc\src\$@.d - del $@.* - -test19933_mingw: - # DFLAGS=-mscrtlib=msvcrt120 takes precedence over any command line flags, so - # specify vcruntime140.lib explicitly for using mingw with Universal CRT - $(DMD) -m$(MODEL) -conf= -Iimport -betterC -Lvcruntime140.lib -Llegacy_stdio_definitions.lib -L/NODEFAULTLIB:msvcrt120.lib -run test\betterc\src\test19933.d - del $@.* diff --git a/runtime/druntime/test/common.mak b/runtime/druntime/test/common.mak index c4afbefa700..132fc7e5891 100644 --- a/runtime/druntime/test/common.mak +++ b/runtime/druntime/test/common.mak @@ -1,4 +1,4 @@ -# set from top makefile +# set explicitly in the make cmdline in druntime/Makefile (`test/%/.run` rule): OS:= MODEL:= BUILD:= @@ -8,30 +8,44 @@ DRUNTIMESO:= LINKDL:= QUIET:= TIMELIMIT:= -LDL:=$(subst -L,,$(LINKDL)) # -ldl +PIC:= + +# Windows: set up bash shell +ifeq (windows,$(OS)) + include ../../../compiler/src/osmodel.mak +endif +LDL:=$(subst -L,,$(LINKDL)) # -ldl SRC:=src GENERATED:=./generated ROOT:=$(GENERATED)/$(OS)/$(BUILD)/$(MODEL) -ifneq (default,$(MODEL)) - MODEL_FLAG:=-m$(MODEL) +MODEL_FLAG:=$(if $(findstring $(MODEL),default),,-m$(MODEL)) +CFLAGS_BASE:=$(if $(findstring $(OS),windows),/Wall,$(MODEL_FLAG) $(PIC) -Wall) +ifeq (osx64,$(OS)$(MODEL)) + CFLAGS_BASE+=--target=x86_64-darwin-apple # ARM cpu is not supported by dmd endif -CFLAGS_BASE:= $(MODEL_FLAG) $(PIC) -Wall -ifeq (osx,$(OS)) - ifeq (64,$(MODEL)) - CFLAGS_BASE+=--target=x86_64-darwin-apple # ARM cpu is not supported by dmd - endif -endif -DFLAGS:=$(MODEL_FLAG) $(PIC) -w -I../../src -I../../import -I$(SRC) -defaultlib= -debuglib= -preview=dip1000 -L-lpthread -L-lm $(LINKDL) +DFLAGS:=$(MODEL_FLAG) $(PIC) -w -I../../src -I../../import -I$(SRC) -defaultlib= -preview=dip1000 $(if $(findstring $(OS),windows),,-L-lpthread -L-lm $(LINKDL)) # LINK_SHARED may be set by importing makefile DFLAGS+=$(if $(LINK_SHARED),-L$(DRUNTIMESO),-L$(DRUNTIME)) ifeq ($(BUILD),debug) - DFLAGS += -g -debug - CFLAGS := $(CFLAGS_BASE) -g + DFLAGS+=-g -debug + CFLAGS:=$(CFLAGS_BASE) $(if $(findstring $(OS),windows),/Zi,-g) else - DFLAGS += -O -release - CFLAGS := $(CFLAGS_BASE) -O3 + DFLAGS+=-O -release + CFLAGS:=$(CFLAGS_BASE) $(if $(findstring $(OS),windows),/O2,-O3) endif -CXXFLAGS_BASE := $(CFLAGS_BASE) +CXXFLAGS_BASE:=$(CFLAGS_BASE) CXXFLAGS:=$(CFLAGS) + +ifeq (windows,$(OS)) + DOTEXE:=.exe + DOTDLL:=.dll + DOTLIB:=.lib + DOTOBJ:=.obj +else + DOTEXE:= + DOTDLL:=$(if $(findstring $(OS),osx),.dylib,.so) + DOTLIB:=.a + DOTOBJ:=.o +endif diff --git a/runtime/druntime/test/config/Makefile b/runtime/druntime/test/config/Makefile index 73ab6118ce6..fd77e770d2a 100644 --- a/runtime/druntime/test/config/Makefile +++ b/runtime/druntime/test/config/Makefile @@ -5,15 +5,15 @@ TESTS:=test19433 test20459 test22523 .PHONY: all clean all: $(addprefix $(ROOT)/,$(addsuffix .done,$(TESTS))) -$(ROOT)/%: $(SRC)/%.d +$(ROOT)/%$(DOTEXE): $(SRC)/%.d $(QUIET)$(DMD) $(DFLAGS) -of$@ $< -$(ROOT)/test19433.done: $(ROOT)/test19433 +$(ROOT)/test19433.done: $(ROOT)/test19433$(DOTEXE) @echo Testing test19433 $(QUIET)$(ROOT)/test19433 --DRT-dont-eat-me @touch $@ -$(ROOT)/test20459.done: $(ROOT)/test20459 +$(ROOT)/test20459.done: $(ROOT)/test20459$(DOTEXE) @echo Testing test20459 $(QUIET)$(ROOT)/test20459 foo bar -- --DRT-gcopts=profile:1 @touch $@ @@ -21,8 +21,8 @@ $(ROOT)/test20459.done: $(ROOT)/test20459 $(ROOT)/test22523.done: $(SRC)/test22523.d @echo Testing $< - $(QUIET)$(DMD) $(DFLAGS) -unittest -of$(ROOT)/test22523 $< - $(QUIET) $(ROOT)/test22523 -- --DRT-testmode=run-main + $(QUIET)$(DMD) $(DFLAGS) -unittest -of$(ROOT)/test22523$(DOTEXE) $< + $(QUIET)$(ROOT)/test22523 -- --DRT-testmode=run-main @touch $@ clean: diff --git a/runtime/druntime/test/coverage/Makefile b/runtime/druntime/test/coverage/Makefile index a3271bab2f0..ba5da368a63 100644 --- a/runtime/druntime/test/coverage/Makefile +++ b/runtime/druntime/test/coverage/Makefile @@ -5,57 +5,73 @@ DFLAGS+=-cov NORMAL_TESTS:=$(addprefix $(ROOT)/,$(addsuffix .done,basic)) MERGE_TESTS:=$(addprefix $(ROOT)/,$(addsuffix .done,merge merge_true)) -DIFF:=diff +DIFF:=diff --strip-trailing-cr SED:=sed ifeq ($(OS),$(filter $(OS),freebsd osx)) - SED_INPLACE:=-i '' + SED_INPLACE:=-i '' else - SED_INPLACE:=-i'' + SED_INPLACE:=-i'' endif .PHONY: all clean all: $(NORMAL_TESTS) $(MERGE_TESTS) $(ROOT)/no_code.done $(ROOT)/merge_override.done -$(NORMAL_TESTS): $(ROOT)/%.done: $(ROOT)/% +$(NORMAL_TESTS): $(ROOT)/%.done: $(ROOT)/%$(DOTEXE) @echo Testing $* @rm -f $(ROOT)/src-$*.lst $(QUIET)$(ROOT)/$* $(ROOT) $(RUN_ARGS) +ifeq (windows,$(OS)) + $(QUIET)$(SED) $(SED_INPLACE) 's:^src\\:src/:g' $(ROOT)/src-$*.lst +endif $(QUIET)$(DIFF) src-$*.lst.exp $(ROOT)/src-$*.lst @touch $@ -$(MERGE_TESTS): $(ROOT)/%.done: $(ROOT)/% +$(MERGE_TESTS): $(ROOT)/%.done: $(ROOT)/%$(DOTEXE) @echo Testing $* @rm -f $(ROOT)/src-$*.lst $(QUIET)$(ROOT)/$* $(ROOT) $(RUN_ARGS) $(QUIET)$(ROOT)/$* $(ROOT) $(RUN_ARGS) +ifeq (windows,$(OS)) + $(QUIET)$(SED) $(SED_INPLACE) 's:^src\\:src/:g' $(ROOT)/src-$*.lst +endif $(QUIET)$(DIFF) src-$*.lst.exp $(ROOT)/src-$*.lst @touch $@ -$(ROOT)/merge_override.done: $(ROOT)/%.done: $(ROOT)/% +$(ROOT)/merge_override.done: $(ROOT)/%.done: $(ROOT)/%$(DOTEXE) @echo Testing $* @rm -f $(ROOT)/src-$*.lst $(QUIET)$(SED) $(SED_INPLACE) 's/CHANGEVAR/CHANGE_VAR/g' src/$*.d $(QUIET)$(ROOT)/$* $(ROOT) $(RUN_ARGS) $(QUIET)$(SED) $(SED_INPLACE) 's/CHANGE_VAR/CHANGEVAR/g' src/$*.d +ifeq (windows,$(OS)) + $(QUIET)$(SED) $(SED_INPLACE) 's:^src\\:src/:g' $(ROOT)/src-$*.lst +endif $(QUIET)$(DIFF) src-$*.lst_1.exp $(ROOT)/src-$*.lst $(QUIET)$(ROOT)/$* $(ROOT) $(RUN_ARGS) $(QUIET)$(SED) $(SED_INPLACE) 's/CHANGEVAR/CHANGE_VAR/g' src/$*.d +ifeq (windows,$(OS)) + $(QUIET)$(SED) $(SED_INPLACE) 's:^src\\:src/:g' $(ROOT)/src-$*.lst +endif $(QUIET)$(DIFF) src-$*.lst_2.exp $(ROOT)/src-$*.lst @touch $@ -$(ROOT)/no_code.done: $(ROOT)/%.done: $(ROOT)/% +$(ROOT)/no_code.done: $(ROOT)/%.done: $(ROOT)/%$(DOTEXE) @echo Testing $* @rm -f $(ROOT)/src-$*.lst $(QUIET)$(ROOT)/$* $(ROOT) $(RUN_ARGS) $(QUIET)$(ROOT)/$* $(ROOT) $(RUN_ARGS) +ifeq (windows,$(OS)) + $(QUIET)$(SED) $(SED_INPLACE) 's:^src\\:src/:g' $(ROOT)/src-$*.lst + $(QUIET)$(SED) $(SED_INPLACE) 's:^src\\:src/:g' $(ROOT)/src-$*_imp.lst +endif $(QUIET)$(DIFF) src-$*.lst.exp $(ROOT)/src-$*.lst $(QUIET)$(DIFF) src-$*_imp.lst.exp $(ROOT)/src-$*_imp.lst @touch $@ -$(ROOT)/no_code: $(SRC)/no_code_imp.d -$(ROOT)/%: $(SRC)/%.d - $(QUIET)$(DMD) $(DFLAGS) -of$(ROOT)/$* $^ +$(ROOT)/no_code$(DOTEXE): $(SRC)/no_code_imp.d +$(ROOT)/%$(DOTEXE): $(SRC)/%.d + $(QUIET)$(DMD) $(DFLAGS) -of$@ $^ clean: rm -rf $(GENERATED) *.lst diff --git a/runtime/druntime/test/cpuid/Makefile b/runtime/druntime/test/cpuid/Makefile index 3998382d1d0..98c499518f6 100644 --- a/runtime/druntime/test/cpuid/Makefile +++ b/runtime/druntime/test/cpuid/Makefile @@ -5,12 +5,12 @@ TESTS:=cpuid .PHONY: all clean all: $(addprefix $(ROOT)/,$(addsuffix .done,$(TESTS))) -$(ROOT)/%.done: $(ROOT)/% +$(ROOT)/%.done: $(ROOT)/%$(DOTEXE) @echo Testing $* $(QUIET)$(TIMELIMIT)$< $(RUN_ARGS) @touch $@ -$(ROOT)/cpuid: $(SRC)/cpuid.d +$(ROOT)/%$(DOTEXE): $(SRC)/%.d $(QUIET)$(DMD) $(DFLAGS) -of$@ $< clean: diff --git a/runtime/druntime/test/cpuid/win64.mak b/runtime/druntime/test/cpuid/win64.mak deleted file mode 100644 index 37796f1e1d1..00000000000 --- a/runtime/druntime/test/cpuid/win64.mak +++ /dev/null @@ -1,12 +0,0 @@ -# built from the druntime top-level folder -# to be overwritten by caller -DMD=dmd -MODEL=64 -DRUNTIMELIB=druntime64.lib - -test: cpuid - -cpuid: - $(DMD) -g -m$(MODEL) -conf= -Iimport -defaultlib=$(DRUNTIMELIB) test\cpuid\src\cpuid.d - cpuid.exe - del cpuid.exe cpuid.obj diff --git a/runtime/druntime/test/cycles/Makefile b/runtime/druntime/test/cycles/Makefile index 41352569cf5..1079ad8ca0f 100644 --- a/runtime/druntime/test/cycles/Makefile +++ b/runtime/druntime/test/cycles/Makefile @@ -11,17 +11,17 @@ all: $(addprefix $(ROOT)/,$(addsuffix .done,$(TESTS))) $(ROOT)/cycle_ignore.done: RETCODE=0 $(ROOT)/cycle_ignore.done: LINES=0 $(ROOT)/cycle_abort.done: RETCODE=1 -$(ROOT)/cycle_abort.done: LINES=7 +$(ROOT)/cycle_abort.done: LINES=$(if $(findstring $(OS),windows),8,7) $(ROOT)/cycle_print.done: RETCODE=0 $(ROOT)/cycle_print.done: LINES=6 $(ROOT)/cycle_deprecate.done: RETCODE=1 -$(ROOT)/cycle_deprecate.done: LINES=8 -$(ROOT)/%.done: $(ROOT)/test_cycles +$(ROOT)/cycle_deprecate.done: LINES=$(if $(findstring $(OS),windows),9,8) +$(ROOT)/%.done: $(ROOT)/test_cycles$(DOTEXE) @echo Testing $* $(QUIET)$(TIMELIMIT)$(ROOT)/test_cycles --DRT-oncycle=$(patsubst cycle_%.done,%, $(notdir $@)) > $@ 2>&1; test $$? -eq $(RETCODE) test `cat $@ | wc -l` -eq $(LINES) -$(ROOT)/test_cycles: $(SRC)/*.d +$(ROOT)/test_cycles$(DOTEXE): $(SRC)/*.d $(QUIET)$(DMD) $(DFLAGS) -of$@ $^ clean: diff --git a/runtime/druntime/test/exceptions/Makefile b/runtime/druntime/test/exceptions/Makefile index be729590fb4..fd975327d9b 100644 --- a/runtime/druntime/test/exceptions/Makefile +++ b/runtime/druntime/test/exceptions/Makefile @@ -1,31 +1,34 @@ include ../common.mak TESTS=stderr_msg unittest_assert invalid_memory_operation unknown_gc static_dtor \ - future_message refcounted rt_trap_exceptions_drt catch_in_finally \ - message_with_null + future_message refcounted rt_trap_exceptions_drt catch_in_finally \ + message_with_null ifeq ($(OS)-$(BUILD),linux-debug) - TESTS+=line_trace line_trace_21656 long_backtrace_trunc rt_trap_exceptions cpp_demangle - LINE_TRACE_DFLAGS:=-L--export-dynamic + TESTS+=line_trace line_trace_21656 long_backtrace_trunc rt_trap_exceptions cpp_demangle + LINE_TRACE_DFLAGS:=-L--export-dynamic endif ifeq ($(OS),linux) - TESTS+=rt_trap_exceptions_drt_gdb + TESTS+=rt_trap_exceptions_drt_gdb endif ifeq ($(OS)-$(BUILD),freebsd-debug) - TESTS+=line_trace line_trace_21656 long_backtrace_trunc cpp_demangle - LINE_TRACE_DFLAGS:=-L--export-dynamic + TESTS+=line_trace line_trace_21656 long_backtrace_trunc cpp_demangle + LINE_TRACE_DFLAGS:=-L--export-dynamic endif ifeq ($(OS)-$(BUILD),dragonflybsd-debug) - TESTS+=line_trace line_trace_21656 long_backtrace_trunc cpp_demangle - LINE_TRACE_DFLAGS:=-L--export-dynamic + TESTS+=line_trace line_trace_21656 long_backtrace_trunc cpp_demangle + LINE_TRACE_DFLAGS:=-L--export-dynamic endif ifeq ($(OS)-$(BUILD),osx-debug) - TESTS+=line_trace line_trace_21656 long_backtrace_trunc cpp_demangle - LINE_TRACE_DFLAGS:= + TESTS+=line_trace line_trace_21656 long_backtrace_trunc cpp_demangle + LINE_TRACE_DFLAGS:= +endif +ifeq ($(OS)-$(BUILD),windows-debug) + TESTS+=winstack endif ifeq ($(BUILD),debug) - TESTS+=assert_fail + TESTS+=assert_fail endif DIFF:=diff @@ -35,7 +38,7 @@ GDB:=gdb .PHONY: all clean all: $(addprefix $(ROOT)/,$(addsuffix .done,$(TESTS))) -$(ROOT)/line_trace.done: $(ROOT)/line_trace +$(ROOT)/line_trace.done: $(ROOT)/line_trace$(DOTEXE) @echo Testing line_trace $(QUIET)$(TIMELIMIT)$(ROOT)/line_trace $(RUN_ARGS) > $(ROOT)/line_trace.output # Use sed to canonicalize line_trace.output and compare against expected output in line_trace.exp @@ -44,7 +47,7 @@ $(ROOT)/line_trace.done: $(ROOT)/line_trace @touch $@ # https://issues.dlang.org/show_bug.cgi?id=21656 -$(ROOT)/line_trace_21656.done: $(ROOT)/line_trace +$(ROOT)/line_trace_21656.done: $(ROOT)/line_trace$(DOTEXE) @echo Testing line_trace_21656 @mkdir -p $(ROOT)/line_trace_21656 @touch $(ROOT)/line_trace_21656/line_trace @@ -53,7 +56,7 @@ $(ROOT)/line_trace_21656.done: $(ROOT)/line_trace @rm -rf $(ROOT)/line_trace_21656 @touch $@ -$(ROOT)/long_backtrace_trunc.done: $(ROOT)/long_backtrace_trunc +$(ROOT)/long_backtrace_trunc.done: $(ROOT)/long_backtrace_trunc$(DOTEXE) @echo Testing long_backtrace_trunc $(QUIET)$(TIMELIMIT)$(ROOT)/long_backtrace_trunc $(RUN_ARGS) > $(ROOT)/long_backtrace_trunc.output # Use sed to canonicalize long_backtrace_trunc.output and compare against expected output in long_backtrace_trunc.exp @@ -61,12 +64,17 @@ $(ROOT)/long_backtrace_trunc.done: $(ROOT)/long_backtrace_trunc @rm -f $(ROOT)/long_backtrace_trunc.output @touch $@ -$(ROOT)/chain.done: $(ROOT)/chain +$(ROOT)/chain.done: $(ROOT)/chain$(DOTEXE) @echo Testing chain $(QUIET)$(TIMELIMIT)$(ROOT)/chain $(RUN_ARGS) > $(ROOT)/chain.output @rm -f $(ROOT)/chain.output @touch $@ +$(ROOT)/winstack.done: $(ROOT)/winstack$(DOTEXE) + @echo Testing winstack + $(QUIET)$(TIMELIMIT)$(ROOT)/winstack $(RUN_ARGS) + @touch $@ + $(ROOT)/stderr_msg.done: STDERR_EXP="stderr_msg msg" $(ROOT)/unittest_assert.done: STDERR_EXP="unittest_assert msg" $(ROOT)/invalid_memory_operation.done: STDERR_EXP="InvalidMemoryOperationError" @@ -82,7 +90,7 @@ $(ROOT)/cpp_demangle.done: STDERR_EXP="thrower(int)" $(ROOT)/message_with_null.done: STDERR_EXP=" world" -$(ROOT)/%.done: $(ROOT)/% +$(ROOT)/%.done: $(ROOT)/%$(DOTEXE) @echo Testing $* $(QUIET)$(TIMELIMIT)$(ROOT)/$* $(RUN_ARGS) 2>$(ROOT)/$*.stderr || true @@ -105,7 +113,7 @@ $(ROOT)/rt_trap_exceptions_drt.done: RUN_ARGS="--DRT-trapExceptions=0" $(ROOT)/rt_trap_exceptions_drt.done: NEGATE=! -$(ROOT)/rt_trap_exceptions_drt_gdb.done: $(ROOT)/rt_trap_exceptions_drt +$(ROOT)/rt_trap_exceptions_drt_gdb.done: $(ROOT)/rt_trap_exceptions_drt$(DOTEXE) @echo Testing rt_trap_exceptions_drt_gdb $(QUIET)$(TIMELIMIT) $(GDB) -n -ex 'set confirm off' -ex run -ex 'bt full' -ex q --args $< --DRT-trapExceptions=0 \ > $(ROOT)/rt_trap_exceptions_drt_gdb.output 2>&1 || true @@ -115,23 +123,23 @@ $(ROOT)/rt_trap_exceptions_drt_gdb.done: $(ROOT)/rt_trap_exceptions_drt ! grep "No stack." > /dev/null < $(ROOT)/rt_trap_exceptions_drt_gdb.output @touch $@ -$(ROOT)/refcounted.done: $(ROOT)/refcounted +$(ROOT)/refcounted.done: $(ROOT)/refcounted$(DOTEXE) $(QUIET) $< @touch $@ -ifeq (ldmd,$(findstring ldmd,$(DMD))) +ifneq (,$(findstring ldmd,$(DMD))) # LDC: Make sure allocation intended to provoke exception is not elided. -$(ROOT)/invalid_memory_operation: DFLAGS+=-disable-gc2stack +$(ROOT)/invalid_memory_operation$(DOTEXE): DFLAGS+=-disable-gc2stack endif -$(ROOT)/unittest_assert: DFLAGS+=-unittest -version=CoreUnittest -$(ROOT)/line_trace: DFLAGS+=$(LINE_TRACE_DFLAGS) -$(ROOT)/long_backtrace_trunc: DFLAGS+=$(LINE_TRACE_DFLAGS) -$(ROOT)/rt_trap_exceptions: DFLAGS+=$(LINE_TRACE_DFLAGS) -$(ROOT)/rt_trap_exceptions_drt: DFLAGS+=-g -$(ROOT)/refcounted: DFLAGS+=-dip1008 -$(ROOT)/cpp_demangle: DFLAGS+=-L-lstdc++ $(LINE_TRACE_DFLAGS) - -$(ROOT)/%: $(SRC)/%.d $(DMD) $(DRUNTIME) +$(ROOT)/unittest_assert$(DOTEXE): DFLAGS+=-unittest -version=CoreUnittest +$(ROOT)/line_trace$(DOTEXE): DFLAGS+=$(LINE_TRACE_DFLAGS) +$(ROOT)/long_backtrace_trunc$(DOTEXE): DFLAGS+=$(LINE_TRACE_DFLAGS) +$(ROOT)/rt_trap_exceptions$(DOTEXE): DFLAGS+=$(LINE_TRACE_DFLAGS) +$(ROOT)/rt_trap_exceptions_drt$(DOTEXE): DFLAGS+=-g +$(ROOT)/refcounted$(DOTEXE): DFLAGS+=-dip1008 +$(ROOT)/cpp_demangle$(DOTEXE): DFLAGS+=-L-lstdc++ $(LINE_TRACE_DFLAGS) + +$(ROOT)/%$(DOTEXE): $(SRC)/%.d $(DMD) $(DRUNTIME) $(QUIET)$(DMD) $(DFLAGS) -of$@ $< clean: diff --git a/runtime/druntime/test/exceptions/win64.mak b/runtime/druntime/test/exceptions/win64.mak deleted file mode 100644 index 621a718ccc6..00000000000 --- a/runtime/druntime/test/exceptions/win64.mak +++ /dev/null @@ -1,10 +0,0 @@ -# built from the druntime top-level folder -# to be overwritten by caller -DMD=dmd -MODEL=64 -DRUNTIMELIB=druntime64.lib - -test: - $(DMD) -m$(MODEL) -conf= -Iimport -defaultlib=$(DRUNTIMELIB) -g test\exceptions\src\winstack.d - winstack.exe - del winstack.* diff --git a/runtime/druntime/test/gc/Makefile b/runtime/druntime/test/gc/Makefile index 2f36164bee5..d1be90ccfb5 100644 --- a/runtime/druntime/test/gc/Makefile +++ b/runtime/druntime/test/gc/Makefile @@ -1,22 +1,29 @@ include ../common.mak -TESTS := attributes sentinel sentinel1 sentinel2 printf memstomp invariant logging \ - precise precisegc forkgc forkgc2 \ - sigmaskgc startbackgc recoverfree nocollect concurrent precise_concurrent hospital +TESTS:=attributes sentinel printf memstomp invariant logging \ + precise precisegc \ + recoverfree nocollect + +ifneq ($(OS),windows) + # some .d files are for Posix only + TESTS+=sentinel1 sentinel2 forkgc forkgc2 sigmaskgc startbackgc + # and some tests require the `fork` GC, only supported on Posix + TEST+=concurrent precise_concurrent hospital +endif ifeq ($(OS),linux) - TESTS+=issue22843 + TESTS+=issue22843 endif -SRC_GC = ../../src/core/internal/gc/impl/conservative/gc.d -SRC = $(SRC_GC) ../../src/rt/lifetime.d +SRC_GC=../../src/core/internal/gc/impl/conservative/gc.d +SRC=$(SRC_GC) ../../src/rt/lifetime.d # ../../src/object.d causes duplicate symbols -UDFLAGS = $(DFLAGS) -unittest -version=CoreUnittest +UDFLAGS=$(DFLAGS) -unittest -version=CoreUnittest .PHONY: all clean all: $(addprefix $(ROOT)/,$(addsuffix .done,$(TESTS))) -$(ROOT)/%.done: $(ROOT)/% +$(ROOT)/%.done: $(ROOT)/%$(DOTEXE) @echo Testing $* $(QUIET)$(TIMELIMIT)$(ROOT)/$* $(RUN_ARGS) @touch $@ @@ -24,7 +31,7 @@ $(ROOT)/%.done: $(ROOT)/% # https://issues.dlang.org/show_bug.cgi?id=22843 # needs to run under valgrind # versions before 3.13.0 don't handle clone() correctly, skip them -$(ROOT)/issue22843.done: $(ROOT)/issue22843 +$(ROOT)/issue22843.done: $(ROOT)/issue22843$(DOTEXE) @echo Testing issue22843 $(QUIET)if ! command -v valgrind >/dev/null; then \ echo valgrind not installed, skipping; \ @@ -35,70 +42,70 @@ $(ROOT)/issue22843.done: $(ROOT)/issue22843 fi @touch $@ -$(ROOT)/sentinel: $(SRC) +$(ROOT)/sentinel$(DOTEXE): $(SRC) $(DMD) -debug=SENTINEL $(UDFLAGS) -main -of$@ $(SRC) -$(ROOT)/sentinel1: $(SRC) sentinel1.d +$(ROOT)/sentinel1$(DOTEXE): $(SRC) sentinel1.d $(DMD) -debug=SENTINEL -debug=GC_RECURSIVE_LOCK $(DFLAGS) sentinel1.d -of$@ $(SRC) -$(ROOT)/sentinel2: $(SRC) sentinel2.d +$(ROOT)/sentinel2$(DOTEXE): $(SRC) sentinel2.d $(DMD) -debug=SENTINEL -debug=GC_RECURSIVE_LOCK $(DFLAGS) sentinel2.d -gx -of$@ $(SRC) -$(ROOT)/printf: $(SRC) +$(ROOT)/printf$(DOTEXE): $(SRC) $(DMD) -debug=PRINTF -debug=PRINTF_TO_FILE -debug=COLLECT_PRINTF $(UDFLAGS) -main -of$@ $(SRC_GC) -$(ROOT)/memstomp: $(SRC) +$(ROOT)/memstomp$(DOTEXE): $(SRC) $(DMD) -debug=MEMSTOMP $(UDFLAGS) -main -of$@ $(SRC) -$(ROOT)/invariant: $(SRC) +$(ROOT)/invariant$(DOTEXE): $(SRC) $(DMD) -debug -debug=INVARIANT -debug=PTRCHECK -debug=PTRCHECK2 $(UDFLAGS) -main -of$@ $(SRC) -$(ROOT)/logging: $(SRC) +$(ROOT)/logging$(DOTEXE): $(SRC) $(DMD) -debug=LOGGING $(UDFLAGS) -main -of$@ $(SRC) -$(ROOT)/precise: $(SRC) +$(ROOT)/precise$(DOTEXE): $(SRC) $(DMD) -debug -debug=INVARIANT -debug=MEMSTOMP $(UDFLAGS) -main -of$@ $(SRC) -$(ROOT)/precise.done: RUN_ARGS += --DRT-gcopt=gc:precise +$(ROOT)/precise.done: RUN_ARGS+=--DRT-gcopt=gc:precise -$(ROOT)/precisegc: $(SRC) precisegc.d +$(ROOT)/precisegc$(DOTEXE): $(SRC) precisegc.d $(DMD) $(UDFLAGS) -gx -of$@ $(SRC) precisegc.d -$(ROOT)/concurrent: $(SRC) +$(ROOT)/concurrent$(DOTEXE): $(SRC) $(DMD) $(UDFLAGS) -main -of$@ $(SRC) -$(ROOT)/concurrent.done: RUN_ARGS += --DRT-gcopt=fork:1 +$(ROOT)/concurrent.done: RUN_ARGS+=--DRT-gcopt=fork:1 -$(ROOT)/precise_concurrent: $(SRC) +$(ROOT)/precise_concurrent$(DOTEXE): $(SRC) $(DMD) $(UDFLAGS) -main -of$@ $(SRC) -$(ROOT)/precise_concurrent.done: RUN_ARGS += "--DRT-gcopt=gc:precise fork:1" +$(ROOT)/precise_concurrent.done: RUN_ARGS+="--DRT-gcopt=gc:precise fork:1" -$(ROOT)/attributes: attributes.d +$(ROOT)/attributes$(DOTEXE): attributes.d $(DMD) $(UDFLAGS) -of$@ attributes.d -$(ROOT)/forkgc: forkgc.d +$(ROOT)/forkgc$(DOTEXE): forkgc.d $(DMD) $(UDFLAGS) -of$@ forkgc.d -$(ROOT)/forkgc2: forkgc2.d +$(ROOT)/forkgc2$(DOTEXE): forkgc2.d $(DMD) $(UDFLAGS) -of$@ forkgc2.d -$(ROOT)/sigmaskgc: sigmaskgc.d +$(ROOT)/sigmaskgc$(DOTEXE): sigmaskgc.d $(DMD) $(UDFLAGS) -of$@ sigmaskgc.d -$(ROOT)/startbackgc: startbackgc.d - $(DMD) $(UDFLAGS) -of$@ sigmaskgc.d +$(ROOT)/startbackgc$(DOTEXE): startbackgc.d + $(DMD) $(UDFLAGS) -of$@ startbackgc.d -$(ROOT)/recoverfree: recoverfree.d +$(ROOT)/recoverfree$(DOTEXE): recoverfree.d $(DMD) $(DFLAGS) -of$@ recoverfree.d -$(ROOT)/nocollect: nocollect.d +$(ROOT)/nocollect$(DOTEXE): nocollect.d $(DMD) $(DFLAGS) -of$@ nocollect.d -$(ROOT)/hospital: hospital.d +$(ROOT)/hospital$(DOTEXE): hospital.d $(DMD) $(DFLAGS) -d -of$@ hospital.d -$(ROOT)/hospital.done: RUN_ARGS += --DRT-gcopt=fork:1 +$(ROOT)/hospital.done: RUN_ARGS+=--DRT-gcopt=fork:1 -$(ROOT)/issue22843: issue22843.d +$(ROOT)/issue22843$(DOTEXE): issue22843.d $(DMD) $(UDFLAGS) -of$@ issue22843.d -$(ROOT)/issue22843.done: RUN_ARGS += "--DRT-gcopt=fork:1 initReserve:0 minPoolSize:1" +$(ROOT)/issue22843.done: RUN_ARGS+="--DRT-gcopt=fork:1 initReserve:0 minPoolSize:1" clean: rm -rf $(ROOT) diff --git a/runtime/druntime/test/gc/win64.mak b/runtime/druntime/test/gc/win64.mak deleted file mode 100644 index 8db7bec80c2..00000000000 --- a/runtime/druntime/test/gc/win64.mak +++ /dev/null @@ -1,58 +0,0 @@ -# built from the druntime top-level folder -# to be overwritten by caller -DMD=dmd -MODEL=64 -DRUNTIMELIB=druntime64.lib - -SRC_GC = src/core/internal/gc/impl/conservative/gc.d -SRC = $(SRC_GC) src/rt/lifetime.d src/object.d -_DFLAGS = -m$(MODEL) -g -conf= -Iimport -Isrc -defaultlib=$(DRUNTIMELIB) -UDFLAGS = $(_DFLAGS) -unittest -version=CoreUnittest -RM = del - -test: sentinel printf memstomp invariant logging precise precisegc recoverfree nocollect - -sentinel: - $(DMD) -debug=SENTINEL $(UDFLAGS) -main -of$@.exe $(SRC) - .\$@.exe - $(RM) $@.exe $@.obj $@.ilk $@.pdb - -printf: - $(DMD) -debug=PRINTF -debug=PRINTF_TO_FILE -debug=COLLECT_PRINTF $(UDFLAGS) -main -of$@.exe $(SRC_GC) - .\$@.exe - $(RM) $@.exe $@.obj $@.ilk $@.pdb gcx.log - -memstomp: - $(DMD) -debug=MEMSTOMP $(UDFLAGS) -main -of$@.exe $(SRC) - .\$@.exe - $(RM) $@.exe $@.obj $@.ilk $@.pdb - -invariant: - $(DMD) -debug -debug=INVARIANT -debug=PTRCHECK -debug=PTRCHECK2 $(UDFLAGS) -main -of$@.exe $(SRC) - .\$@.exe - $(RM) $@.exe $@.obj $@.ilk $@.pdb - -logging: - $(DMD) -debug=LOGGING $(UDFLAGS) -of$@.exe -main $(SRC) - .\$@.exe - $(RM) $@.exe $@.obj $@.ilk $@.pdb - -precise: - $(DMD) -debug -debug=INVARIANT -debug=MEMSTOMP $(UDFLAGS) -main -of$@.exe $(SRC) - .\$@.exe --DRT-gcopt=gc:precise - $(RM) $@.exe $@.obj $@.ilk $@.pdb - -precisegc: - $(DMD) $(UDFLAGS) -of$@.exe -gx $(SRC) test/gc/precisegc.d - .\$@.exe - $(RM) $@.exe $@.obj $@.ilk $@.pdb - -recoverfree: - $(DMD) $(_DFLAGS) -of$@.exe -gx test/gc/recoverfree.d - .\$@.exe - $(RM) $@.exe $@.obj $@.ilk $@.pdb - -nocollect: - $(DMD) $(_DFLAGS) -of$@.exe -gx test/gc/nocollect.d - .\$@.exe - $(RM) $@.exe $@.obj $@.ilk $@.pdb diff --git a/runtime/druntime/test/hash/Makefile b/runtime/druntime/test/hash/Makefile index dfd07c88c55..53e0e37936a 100644 --- a/runtime/druntime/test/hash/Makefile +++ b/runtime/druntime/test/hash/Makefile @@ -5,12 +5,12 @@ TESTS:=test_hash .PHONY: all clean all: $(addprefix $(ROOT)/,$(addsuffix .done,$(TESTS))) -$(ROOT)/test_hash.done: $(ROOT)/%.done : $(ROOT)/% +$(ROOT)/%.done: $(ROOT)/%$(DOTEXE) @echo Testing $* $(QUIET)$(TIMELIMIT)$(ROOT)/$* $(RUN_ARGS) @touch $@ -$(ROOT)/%: $(SRC)/%.d +$(ROOT)/%$(DOTEXE): $(SRC)/%.d $(QUIET)$(DMD) $(DFLAGS) -of$@ $< clean: diff --git a/runtime/druntime/test/imports/Makefile b/runtime/druntime/test/imports/Makefile index e4f67668885..078c863798f 100644 --- a/runtime/druntime/test/imports/Makefile +++ b/runtime/druntime/test/imports/Makefile @@ -8,7 +8,7 @@ all: $(addprefix $(ROOT)/,$(addsuffix .done,$(TESTS))) $(ROOT)/%.done: @echo Testing $* @mkdir -p $(basename $@) - $(QUIET)$(DMD) -version=Shared -o- -deps=$@ -Isrc -I../../import src/$* + $(QUIET)$(DMD) -version=Shared -o- -deps=$@ -Isrc -I../../import src/$*.d clean: rm -rf $(GENERATED) diff --git a/runtime/druntime/test/init_fini/Makefile b/runtime/druntime/test/init_fini/Makefile index 846966f7637..0956df48ee9 100644 --- a/runtime/druntime/test/init_fini/Makefile +++ b/runtime/druntime/test/init_fini/Makefile @@ -5,12 +5,12 @@ TESTS:=thread_join runtime_args test18996 custom_gc .PHONY: all clean all: $(addprefix $(ROOT)/,$(addsuffix .done,$(TESTS))) -$(ROOT)/%.done: $(ROOT)/% +$(ROOT)/%.done: $(ROOT)/%$(DOTEXE) @echo Testing $* $(QUIET)$(TIMELIMIT)$(ROOT)/$* $(RUN_ARGS) @touch $@ -$(ROOT)/%: $(SRC)/%.d +$(ROOT)/%$(DOTEXE): $(SRC)/%.d $(QUIET)$(DMD) $(DFLAGS) -of$@ $< clean: diff --git a/runtime/druntime/test/init_fini/win64.mak b/runtime/druntime/test/init_fini/win64.mak deleted file mode 100644 index 1a829b675d3..00000000000 --- a/runtime/druntime/test/init_fini/win64.mak +++ /dev/null @@ -1,12 +0,0 @@ -# built from the druntime top-level folder -# to be overwritten by caller -DMD=dmd -MODEL=64 -DRUNTIMELIB=druntime64.lib - -test: custom_gc - -custom_gc: - $(DMD) -m$(MODEL) -conf= -Iimport -defaultlib=$(DRUNTIMELIB) test\init_fini\src\custom_gc.d - custom_gc.exe - del custom_gc.exe custom_gc.obj diff --git a/runtime/druntime/test/lifetime/Makefile b/runtime/druntime/test/lifetime/Makefile index 40499c3522d..c8cb5895cda 100644 --- a/runtime/druntime/test/lifetime/Makefile +++ b/runtime/druntime/test/lifetime/Makefile @@ -5,12 +5,12 @@ TESTS:=large_aggregate_destroy_21097 .PHONY: all clean all: $(addprefix $(ROOT)/,$(addsuffix .done,$(TESTS))) -$(ROOT)/%.done: $(ROOT)/% +$(ROOT)/%.done: $(ROOT)/%$(DOTEXE) @echo Testing $* $(QUIET)$(TIMELIMIT)$(ROOT)/$* $(RUN_ARGS) @touch $@ -$(ROOT)/%: $(SRC)/%.d +$(ROOT)/%$(DOTEXE): $(SRC)/%.d $(QUIET)$(DMD) $(DFLAGS) -of$@ $< clean: diff --git a/runtime/druntime/test/profile/Makefile b/runtime/druntime/test/profile/Makefile index ac381914f4a..6a9df698efb 100644 --- a/runtime/druntime/test/profile/Makefile +++ b/runtime/druntime/test/profile/Makefile @@ -2,8 +2,9 @@ include ../common.mak TESTS:=profile profilegc both -DIFF:=diff +DIFF:=diff --strip-trailing-cr GREP:=grep +SED:=sed ifeq (freebsd,$(OS)) SHELL=/usr/local/bin/bash @@ -13,7 +14,7 @@ else ifeq (netbsd,$(OS)) SHELL=/usr/pkg/bin/bash else ifeq (dragonflybsd,$(OS)) SHELL=/usr/local/bin/bash -else +else ifneq (windows,$(OS)) # already using a bash shell on Windows via common.mak SHELL=/bin/bash endif @@ -21,7 +22,7 @@ endif all: $(addprefix $(ROOT)/,$(addsuffix .done,$(TESTS))) $(ROOT)/profile.done: DFLAGS+=-profile -$(ROOT)/profile.done: $(ROOT)/%.done: $(ROOT)/% +$(ROOT)/profile.done: $(ROOT)/%.done: $(ROOT)/%$(DOTEXE) @echo Testing $* @rm -f $(ROOT)/mytrace.log $(ROOT)/mytrace.def $(QUIET)$(TIMELIMIT)$(ROOT)/$* $(ROOT)/mytrace.log $(ROOT)/mytrace.def @@ -33,17 +34,17 @@ $(ROOT)/profile.done: $(ROOT)/%.done: $(ROOT)/% @touch $@ $(ROOT)/profilegc.done: DFLAGS+=-profile=gc -$(ROOT)/profilegc.done: $(ROOT)/%.done: $(ROOT)/% +$(ROOT)/profilegc.done: $(ROOT)/%.done: $(ROOT)/%$(DOTEXE) @echo Testing $* @rm -f $(ROOT)/myprofilegc.log $(QUIET)$(TIMELIMIT)$(ROOT)/$* $(ROOT)/myprofilegc.log $(QUIET)$(DIFF) \ - <($(GREP) -vF 'core.' myprofilegc.log.$(OS).$(MODEL).exp) \ + <($(GREP) -vF 'core.' myprofilegc.log.$(OS).$(shell echo $(MODEL) | cut -c 1-2).exp) \ <($(GREP) -vF 'core.' $(ROOT)/myprofilegc.log) @touch $@ $(ROOT)/both.done: DFLAGS+=-profile -profile=gc -$(ROOT)/both.done: $(ROOT)/%.done: $(ROOT)/% +$(ROOT)/both.done: $(ROOT)/%.done: $(ROOT)/%$(DOTEXE) @echo Testing $* @rm -f $(ROOT)/both.log $(ROOT)/both.def $(ROOT)/bothgc.log $(QUIET)$(TIMELIMIT)$(ROOT)/$* $(ROOT)/both.log $(ROOT)/both.def $(ROOT)/bothgc.log @@ -52,12 +53,18 @@ $(ROOT)/both.done: $(ROOT)/%.done: $(ROOT)/% $(QUIET) cat $(ROOT)/both.def $(QUIET) sort $(ROOT)/both.def -o $(ROOT)/both.def $(QUIET)(sort bothnew.def.exp | $(DIFF) - $(ROOT)/both.def) +ifeq (windows,$(OS)) + $(QUIET)$(DIFF) \ + <($(GREP) -vF 'core.' bothgc.log.exp) \ + <($(GREP) -vF 'core.' $(ROOT)/bothgc.log | $(SED) 's: src\\\\: src/:g') +else $(QUIET)$(DIFF) \ <($(GREP) -vF 'core.' bothgc.log.exp) \ <($(GREP) -vF 'core.' $(ROOT)/bothgc.log) +endif @touch $@ -$(ROOT)/%: $(SRC)/%.d +$(ROOT)/%$(DOTEXE): $(SRC)/%.d $(QUIET)$(DMD) $(DFLAGS) -of$(ROOT)/$* $< clean: diff --git a/runtime/druntime/test/profile/myprofilegc.log.windows.32.exp b/runtime/druntime/test/profile/myprofilegc.log.windows.32.exp new file mode 100644 index 00000000000..8b4cdf6e751 --- /dev/null +++ b/runtime/druntime/test/profile/myprofilegc.log.windows.32.exp @@ -0,0 +1,21 @@ +bytes allocated, allocations, type, function, file:line + 256 1 immutable(char)[][int] D main src\profilegc.d:23 + 128 1 float D main src\profilegc.d:18 + 128 1 int D main src\profilegc.d:15 + 64 1 double[] profilegc.main src\profilegc.d:56 + 48 1 float[] D main src\profilegc.d:42 + 48 1 int[] D main src\profilegc.d:41 + 32 1 void[] profilegc.main src\profilegc.d:55 + 16 1 C D main src\profilegc.d:12 + 16 1 char[] D main src\profilegc.d:34 + 16 1 char[] D main src\profilegc.d:36 + 16 1 closure profilegc.main.foo src\profilegc.d:45 + 16 1 float D main src\profilegc.d:16 + 16 1 float D main src\profilegc.d:17 + 16 1 int D main src\profilegc.d:13 + 16 1 int D main src\profilegc.d:14 + 16 1 int[] D main src\profilegc.d:22 + 16 1 int[] D main src\profilegc.d:37 + 16 1 uint[] D main src\profilegc.d:15 + 16 1 uint[] D main src\profilegc.d:18 + 16 1 wchar[] D main src\profilegc.d:35 diff --git a/runtime/druntime/test/profile/myprofilegc.log.windows.64.exp b/runtime/druntime/test/profile/myprofilegc.log.windows.64.exp new file mode 100644 index 00000000000..05408557a84 --- /dev/null +++ b/runtime/druntime/test/profile/myprofilegc.log.windows.64.exp @@ -0,0 +1,21 @@ +bytes allocated, allocations, type, function, file:line + 496 1 immutable(char)[][int] D main src\profilegc.d:23 + 160 1 float D main src\profilegc.d:18 + 160 1 int D main src\profilegc.d:15 + 64 1 double[] profilegc.main src\profilegc.d:56 + 48 1 float[] D main src\profilegc.d:42 + 48 1 int[] D main src\profilegc.d:41 + 32 1 C D main src\profilegc.d:12 + 32 1 ulong[] D main src\profilegc.d:15 + 32 1 ulong[] D main src\profilegc.d:18 + 32 1 void[] profilegc.main src\profilegc.d:55 + 16 1 char[] D main src\profilegc.d:34 + 16 1 char[] D main src\profilegc.d:36 + 16 1 closure profilegc.main.foo src\profilegc.d:45 + 16 1 float D main src\profilegc.d:16 + 16 1 float D main src\profilegc.d:17 + 16 1 int D main src\profilegc.d:13 + 16 1 int D main src\profilegc.d:14 + 16 1 int[] D main src\profilegc.d:22 + 16 1 int[] D main src\profilegc.d:37 + 16 1 wchar[] D main src\profilegc.d:35 diff --git a/runtime/druntime/test/shared/Makefile b/runtime/druntime/test/shared/Makefile index 531f0385b79..a2acdc8dcf9 100644 --- a/runtime/druntime/test/shared/Makefile +++ b/runtime/druntime/test/shared/Makefile @@ -1,6 +1,6 @@ LINK_SHARED:=1 -include ../common.mak +include ../common.mak # affected by LINK_SHARED! TESTS:=link load linkD linkDR loadDR host finalize dynamiccast TESTS+=link_linkdep load_linkdep link_loaddep load_loaddep load_13414 diff --git a/runtime/druntime/test/thread/Makefile b/runtime/druntime/test/thread/Makefile index 6dbe948eb14..041c527c56a 100644 --- a/runtime/druntime/test/thread/Makefile +++ b/runtime/druntime/test/thread/Makefile @@ -1,40 +1,45 @@ include ../common.mak -TESTS:=fiber_guard_page external_threads tlsgc_sections test_import tlsstack join_detach +TESTS:=tlsgc_sections test_import tlsstack join_detach + +# some .d files support Posix only +ifneq ($(OS),windows) + TEST+=fiber_guard_page external_threads +endif .PHONY: all clean all: $(addprefix $(ROOT)/,$(addsuffix .done,$(TESTS))) # segfault || bus error (OSX) -$(ROOT)/fiber_guard_page.done: $(ROOT)/%.done : $(ROOT)/% +$(ROOT)/fiber_guard_page.done: $(ROOT)/%.done : $(ROOT)/%$(DOTEXE) @echo Testing $* $(QUIET)$(TIMELIMIT)$(ROOT)/$* $(RUN_ARGS); rc=$$?; [ $$rc -eq 139 ] || [ $$rc -eq 138 ] @touch $@ -$(ROOT)/external_threads.done: $(ROOT)/%.done : $(ROOT)/% +$(ROOT)/external_threads.done: $(ROOT)/%.done : $(ROOT)/%$(DOTEXE) @echo Testing $* $(QUIET)$(TIMELIMIT)$(ROOT)/$* @touch $@ -$(ROOT)/tlsgc_sections.done: $(ROOT)/%.done : $(ROOT)/% +$(ROOT)/tlsgc_sections.done: $(ROOT)/%.done : $(ROOT)/%$(DOTEXE) @echo Testing $* $(QUIET)$(TIMELIMIT)$(ROOT)/$* @touch $@ -$(ROOT)/test_import.done: $(ROOT)/%.done : $(ROOT)/% +$(ROOT)/test_import.done: $(ROOT)/%.done : $(ROOT)/%$(DOTEXE) @echo Testing $* $(QUIET)$(TIMELIMIT)$(ROOT)/$* @touch $@ -$(ROOT)/tlsstack.done: $(ROOT)/%.done : $(ROOT)/% +$(ROOT)/tlsstack.done: $(ROOT)/%.done : $(ROOT)/%$(DOTEXE) @echo Testing $* $(QUIET)$(TIMELIMIT)$(ROOT)/$* @touch $@ -$(ROOT)/join_detach.done: $(ROOT)/%.done : $(ROOT)/% +$(ROOT)/join_detach.done: $(ROOT)/%.done : $(ROOT)/%$(DOTEXE) @echo Testing $* is currently disabled! -$(ROOT)/%: $(SRC)/%.d +$(ROOT)/%$(DOTEXE): $(SRC)/%.d $(QUIET)$(DMD) $(DFLAGS) -of$@ $< clean: diff --git a/runtime/druntime/test/traits/Makefile b/runtime/druntime/test/traits/Makefile index 0a8ba2bd900..610f7d53193 100644 --- a/runtime/druntime/test/traits/Makefile +++ b/runtime/druntime/test/traits/Makefile @@ -5,12 +5,12 @@ TESTS:=all_satisfy .PHONY: all clean all: $(addprefix $(ROOT)/,$(addsuffix .done,$(TESTS))) -$(ROOT)/%.done: $(ROOT)/% +$(ROOT)/%.done: $(ROOT)/%$(DOTEXE) @echo Testing $* $(QUIET)$(TIMELIMIT)$(ROOT)/$* $(RUN_ARGS) @touch $@ -$(ROOT)/%: $(SRC)/%.d +$(ROOT)/%$(DOTEXE): $(SRC)/%.d $(QUIET)$(DMD) $(DFLAGS) -of$@ $< clean: diff --git a/runtime/druntime/test/typeinfo/Makefile b/runtime/druntime/test/typeinfo/Makefile index e2bb0f5b9ca..338f19c8107 100644 --- a/runtime/druntime/test/typeinfo/Makefile +++ b/runtime/druntime/test/typeinfo/Makefile @@ -5,12 +5,12 @@ TESTS:=comparison isbaseof enum_ .PHONY: all clean all: $(addprefix $(ROOT)/,$(addsuffix .done,$(TESTS))) -$(ROOT)/%.done: $(ROOT)/% +$(ROOT)/%.done: $(ROOT)/%$(DOTEXE) @echo Testing $* $(QUIET)$(TIMELIMIT)$(ROOT)/$* $(RUN_ARGS) @touch $@ -$(ROOT)/%: $(SRC)/%.d +$(ROOT)/%$(DOTEXE): $(SRC)/%.d $(QUIET)$(DMD) $(DFLAGS) -of$@ $< clean: diff --git a/runtime/druntime/test/unittest/Makefile b/runtime/druntime/test/unittest/Makefile index afec263077f..e7c8f032cbf 100644 --- a/runtime/druntime/test/unittest/Makefile +++ b/runtime/druntime/test/unittest/Makefile @@ -34,11 +34,12 @@ $(ROOT)/na.done: TESTTEXT= $(ROOT)/%.done: customhandler.d @echo Testing $* - $(QUIET)$(DMD) $(DFLAGS) -of$(ROOT)/tester_$(patsubst %.done,%, $(notdir $@)) customhandler.d -version=$(VER) + $(QUIET)$(DMD) $(DFLAGS) -of$(ROOT)/tester_$(patsubst %.done,%, $(notdir $@))$(DOTEXE) customhandler.d -version=$(VER) $(QUIET)$(TIMELIMIT)$(ROOT)/tester_$(patsubst %.done,%, $(notdir $@)) > $@ 2>&1; test $$? -eq $(RETCODE) $(QUIET)test $(HASMAIN) -eq 0 || grep -q main $@ $(QUIET)test $(HASMAIN) -eq 1 || ! grep -q main $@ $(QUIET)test -z "$(TESTTEXT)" || grep -q "$(TESTTEXT) unittests" $@ $(QUIET)test -n "$(TESTTEXT)" || ! grep -q "unittests" $@ + clean: rm -rf $(GENERATED) diff --git a/runtime/druntime/test/uuid/Makefile b/runtime/druntime/test/uuid/Makefile new file mode 100644 index 00000000000..9e6ffc926ee --- /dev/null +++ b/runtime/druntime/test/uuid/Makefile @@ -0,0 +1,23 @@ +include ../common.mak + +SUPPORTED:=0 +ifeq (windows,$(OS)) + ifneq (32omf,$(MODEL)) + SUPPORTED:=1 + endif +endif + +.PHONY: all clean + +ifneq (1,$(SUPPORTED)) +all: + @echo "Skipping uuid test on platforms other than Windows MSVC" +else +all: $(ROOT)/test$(DOTEXE) + +$(ROOT)/%$(DOTEXE): %.d + $(QUIET)$(DMD) $(DFLAGS) -of$@ $< uuid.lib +endif + +clean: + rm -rf $(ROOT) diff --git a/runtime/druntime/test/uuid/win64.mak b/runtime/druntime/test/uuid/win64.mak deleted file mode 100644 index ddf9c0c8485..00000000000 --- a/runtime/druntime/test/uuid/win64.mak +++ /dev/null @@ -1,9 +0,0 @@ -# built from the druntime top-level folder -# to be overwritten by caller -DMD=dmd -MODEL=64 -DRUNTIMELIB=druntime64.lib - -test: - $(DMD) -m$(MODEL) -conf= -Iimport -defaultlib=$(DRUNTIMELIB) test\uuid\test.d uuid.lib - del test.exe test.obj diff --git a/runtime/druntime/test/valgrind/Makefile b/runtime/druntime/test/valgrind/Makefile index 3ac82f72737..2967aff4deb 100644 --- a/runtime/druntime/test/valgrind/Makefile +++ b/runtime/druntime/test/valgrind/Makefile @@ -1,8 +1,13 @@ include ../common.mak -TESTS := ok_append no_use_after_free no_oob no_oob_sentinel no_use_after_gc +ifeq (windows,$(OS)) + # no valgrind on Windows + TESTS:= +else + TESTS:=ok_append no_use_after_free no_oob no_oob_sentinel no_use_after_gc +endif -GC_SRC = \ +GC_SRC:= \ ../../src/core/internal/gc/impl/conservative/gc.d \ ../../src/etc/valgrind/valgrind.d \ ../../src/rt/lifetime.d @@ -10,7 +15,7 @@ GC_SRC = \ .PHONY: all clean all: $(addprefix $(ROOT)/,$(addsuffix .done,$(TESTS))) -$(ROOT)/ok_%.done: $(ROOT)/ok_% +$(ROOT)/ok_%.done: $(ROOT)/ok_%$(DOTEXE) @echo Testing ok_$* $(QUIET)if ! command -v valgrind >/dev/null; then \ echo valgrind not installed, skipping; \ @@ -19,7 +24,7 @@ $(ROOT)/ok_%.done: $(ROOT)/ok_% fi $(QUIET)touch $@ -$(ROOT)/no_%.done: $(ROOT)/no_% +$(ROOT)/no_%.done: $(ROOT)/no_%$(DOTEXE) @echo Testing no_$* $(QUIET)if ! command -v valgrind >/dev/null; then \ echo valgrind not installed, skipping; \ @@ -28,7 +33,8 @@ $(ROOT)/no_%.done: $(ROOT)/no_% fi $(QUIET)touch $@ -$(ROOT)/%: $(SRC)/%.d $(GC_SRC) +$(ROOT)/%$(DOTEXE): $(SRC)/%.d $(GC_SRC) $(QUIET)$(DMD) -debug=VALGRIND -debug=SENTINEL $(DFLAGS) -of$@ $< $(GC_SRC) + clean: rm -rf $(ROOT) diff --git a/runtime/druntime/win32.mak b/runtime/druntime/win32.mak deleted file mode 100644 index 37b96e33ac6..00000000000 --- a/runtime/druntime/win32.mak +++ /dev/null @@ -1,45 +0,0 @@ -# Makefile to build D runtime library druntime.lib for Win32 OMF -# MS COFF builds use win64.mak for 32 and 64 bit - -# Ignored, only the default value is supported -#MODEL=32omf - -DMD_DIR=..\compiler -BUILD=release -OS=windows -DMD=$(DMD_DIR)\..\generated\$(OS)\$(BUILD)\32\dmd - -# Used for running MASM assembler on .asm files -CC=dmc - -MAKE=make - -DRUNTIME=$(DMD_DIR)\..\generated\$(OS)\$(BUILD)\32omf\druntime.lib - -################### tests ###################################### - -test_aa: - $(DMD) -m32omf -conf= -Isrc -defaultlib=$(DRUNTIME) -run test\aa\src\test_aa.d - -test_allocations: - "$(MAKE)" -f test\allocations\win64.mak "DMD=$(DMD)" MODEL=32omf "VCDIR=$(VCDIR)" DRUNTIMELIB=$(DRUNTIME) "CC=$(CC)" test - -test_cpuid: - "$(MAKE)" -f test\cpuid\win64.mak "DMD=$(DMD)" MODEL=32omf "VCDIR=$(VCDIR)" DRUNTIMELIB=$(DRUNTIME) "CC=$(CC)" test - -test_exceptions: - "$(MAKE)" -f test\exceptions\win64.mak "DMD=$(DMD)" MODEL=32omf "VCDIR=$(VCDIR)" DRUNTIMELIB=$(DRUNTIME) "CC=$(CC)" test - -test_hash: - $(DMD) -m32omf -conf= -Isrc -defaultlib=$(DRUNTIME) -run test\hash\src\test_hash.d - -test_gc: - "$(MAKE)" -f test\gc\win64.mak "DMD=$(DMD)" MODEL=32omf "VCDIR=$(VCDIR)" DRUNTIMELIB=$(DRUNTIME) "CC=$(CC)" test - -custom_gc: - $(MAKE) -f test\init_fini\win64.mak "DMD=$(DMD)" MODEL=32omf "VCDIR=$(VCDIR)" DRUNTIMELIB=$(DRUNTIME) "CC=$(CC)" test - -test_shared: - $(MAKE) -f test\shared\win64.mak "DMD=$(DMD)" MODEL=32omf "VCDIR=$(VCDIR)" DRUNTIMELIB=$(DRUNTIME) "CC=$(CC)" test - -test_all: test_aa test_allocations test_cpuid test_exceptions test_hash test_gc custom_gc test_shared diff --git a/runtime/druntime/win64.mak b/runtime/druntime/win64.mak deleted file mode 100644 index 658a6a3eafc..00000000000 --- a/runtime/druntime/win64.mak +++ /dev/null @@ -1,65 +0,0 @@ -# Makefile to build D runtime library lib\druntime64.lib for 64 bit Windows and -# lib\druntime32mscoff.lib for 32 bit Windows. Both are for use with the MSVC toolchain. - -# Determines whether lib\druntime32mscoff.lib is built or lib\druntime64.lib -# Set to `32mscoff` for a 32-bit build, `64` for 64-bit build. -MODEL=64 - -DMD_DIR=..\compiler - -BUILD=release -OS=windows - -# The D compiler used to build things -DMD=$(DMD_DIR)\..\generated\$(OS)\$(BUILD)\$(MODEL)\dmd - -# Make program to use. Designed to be run with make.exe which can be obtained from -# https://downloads.dlang.org/other/dm857c.zip -MAKE=make - -DRUNTIME=$(DMD_DIR)\..\generated\$(OS)\$(BUILD)\$(MODEL)\druntime.lib - -################### tests ###################################### - -test_uuid: - "$(MAKE)" -f test\uuid\win64.mak "DMD=$(DMD)" MODEL=$(MODEL) DRUNTIMELIB=$(DRUNTIME) test - -test_aa: - "$(DMD)" -m$(MODEL) -conf= -Isrc -defaultlib=$(DRUNTIME) -run test\aa\src\test_aa.d - -test_allocations: - "$(MAKE)" -f test\allocations\win64.mak "DMD=$(DMD)" MODEL=$(MODEL) DRUNTIMELIB=$(DRUNTIME) test - -test_betterc: - "$(MAKE)" -f test\betterc\win64.mak "DMD=$(DMD)" MODEL=$(MODEL) DRUNTIMELIB=$(DRUNTIME) test - -test_betterc_mingw: - "$(MAKE)" -f test\betterc\win64.mak "DMD=$(DMD)" MODEL=$(MODEL) DRUNTIMELIB=$(DRUNTIME) MINGW=_mingw test - -test_cpuid: - "$(MAKE)" -f test\cpuid\win64.mak "DMD=$(DMD)" MODEL=$(MODEL) DRUNTIMELIB=$(DRUNTIME) test - -test_exceptions: - "$(MAKE)" -f test\exceptions\win64.mak "DMD=$(DMD)" MODEL=$(MODEL) DRUNTIMELIB=$(DRUNTIME) test - -test_hash: - "$(DMD)" -m$(MODEL) -conf= -Isrc -defaultlib=$(DRUNTIME) -run test\hash\src\test_hash.d - -test_stdcpp: - setmscver.bat - "$(MAKE)" -f test\stdcpp\win64.mak "DMD=$(DMD)" MODEL=$(MODEL) DRUNTIMELIB=$(DRUNTIME) test - -test_gc: - "$(MAKE)" -f test\gc\win64.mak "DMD=$(DMD)" MODEL=$(MODEL) DRUNTIMELIB=$(DRUNTIME) test - -custom_gc: - $(MAKE) -f test\init_fini\win64.mak "DMD=$(DMD)" MODEL=$(MODEL) DRUNTIMELIB=$(DRUNTIME) test - -test_shared: - $(MAKE) -f test\shared\win64.mak "DMD=$(DMD)" MODEL=$(MODEL) DRUNTIMELIB=$(DRUNTIME) test - -test_common: test_shared test_aa test_allocations test_cpuid test_exceptions test_hash test_gc custom_gc - -test_mingw: test_common test_betterc_mingw - -test_all: test_common test_betterc test_uuid test_stdcpp From bc3d92d28deafe4096423748501caf68d712127d Mon Sep 17 00:00:00 2001 From: Martin Kinkelin Date: Sun, 10 Dec 2023 02:59:32 +0100 Subject: [PATCH 122/215] druntime: Merge test/stdcpp/win64.mak into Makefile --- runtime/druntime/Makefile | 2 +- runtime/druntime/test/stdcpp/Makefile | 107 +++++++++++++++++-------- runtime/druntime/test/stdcpp/msc_ver.c | 1 + runtime/druntime/test/stdcpp/win64.mak | 38 --------- 4 files changed, 74 insertions(+), 74 deletions(-) create mode 100644 runtime/druntime/test/stdcpp/msc_ver.c delete mode 100644 runtime/druntime/test/stdcpp/win64.mak diff --git a/runtime/druntime/Makefile b/runtime/druntime/Makefile index 7feb67a2ffb..74682f25408 100644 --- a/runtime/druntime/Makefile +++ b/runtime/druntime/Makefile @@ -416,7 +416,7 @@ ifeq ($(HAS_ADDITIONAL_TESTS),1) test/aa test/cpuid test/gc test/hash test/lifetime \ test/thread test/unittest test/imports test/betterc test/config \ test/traits test/uuid test/valgrind - ifneq (windows,$(OS)) # FIXME + ifneq (32omf,$(MODEL)) ADDITIONAL_TESTS+=test/stdcpp endif ADDITIONAL_TESTS+=$(if $(SHARED),test/shared,) diff --git a/runtime/druntime/test/stdcpp/Makefile b/runtime/druntime/test/stdcpp/Makefile index a05ee35a998..f3c150bb33d 100644 --- a/runtime/druntime/test/stdcpp/Makefile +++ b/runtime/druntime/test/stdcpp/Makefile @@ -1,5 +1,42 @@ include ../common.mak +.PHONY: all clean + +ifeq (windows,$(OS)) + +CC:=cl +EXTRA_CXXFLAGS:=/EHsc +EXTRA_DFLAGS:= + +TESTS:=allocator array memory new string utility vector + +MSC_VER:=$(strip $(shell $(CC) /nologo /EP msc_ver.c)) +ifeq ($(shell test $(MSC_VER) -gt 1900; echo $$?),0) + EXTRA_CXXFLAGS+=/std:c++17 + EXTRA_DFLAGS+=-extern-std=c++17 + TESTS+=string_view +endif + +all: $(addprefix $(ROOT)/,$(TESTS)) + +$(ROOT)/%: $(SRC)/%.cpp $(SRC)/%_test.d + @echo Testing $* + @mkdir -p $(dir $@) + + $(QUIET)$(CC) /MT $(EXTRA_CXXFLAGS) -c /Fo$@_cpp$(DOTOBJ) $< + $(QUIET)$(DMD) -mscrtlib=libcmt $(DFLAGS) $(EXTRA_DFLAGS) -main -unittest -version=CoreUnittest -version=_MSC_VER_$(MSC_VER) $@_cpp$(DOTOBJ) -run $(SRC)/$*_test.d + + $(QUIET)$(CC) /MD $(EXTRA_CXXFLAGS) -c /Fo$@_cpp$(DOTOBJ) $< + $(QUIET)$(DMD) -mscrtlib=msvcrt $(DFLAGS) $(EXTRA_DFLAGS) -main -unittest -version=CoreUnittest -version=_MSC_VER_$(MSC_VER) $@_cpp$(DOTOBJ) -run $(SRC)/$*_test.d + + $(QUIET)$(CC) /MTd $(EXTRA_CXXFLAGS) -c /Fo$@_cpp$(DOTOBJ) $< + $(QUIET)$(DMD) -mscrtlib=libcmtd $(DFLAGS) $(EXTRA_DFLAGS) -main -unittest -version=CoreUnittest -version=_MSC_VER_$(MSC_VER) $@_cpp$(DOTOBJ) -run $(SRC)/$*_test.d + + $(QUIET)$(CC) /MDd $(EXTRA_CXXFLAGS) -c /Fo$@_cpp$(DOTOBJ) $< + $(QUIET)$(DMD) -mscrtlib=msvcrtd $(DFLAGS) $(EXTRA_DFLAGS) -main -unittest -version=CoreUnittest -version=_MSC_VER_$(MSC_VER) $@_cpp$(DOTOBJ) -run $(SRC)/$*_test.d + +else # Posix: + HASCPP17:=`echo wow | $(CXX) -std=c++17 -E -xc++ - > /dev/null 2>&1 && echo yes` TESTS:=allocator new utility @@ -8,73 +45,73 @@ TESTS17:=string_view OLDABITESTS:= ifeq (osx,$(OS)) - TESTS11+=memory -# TESTS+=string -# TESTS+=vector + TESTS11+=memory +# TESTS+=string +# TESTS+=vector endif ifeq (linux,$(OS)) - TESTS11+=exception typeinfo - TESTS+=typeinfo -# TESTS+=string -# TESTS+=vector - OLDABITESTS+=string + TESTS11+=exception typeinfo + TESTS+=typeinfo +# TESTS+=string +# TESTS+=vector + OLDABITESTS+=string endif ifeq (freebsd,$(OS)) - TESTS11+=memory - TESTS+=string -# TESTS+=vector + TESTS11+=memory + TESTS+=string +# TESTS+=vector endif # some build machines have ancient compilers, so we need to disable C++17 tests ifneq (yes,$(HASCPP17)) -TESTS17:= + TESTS17:= endif -.PHONY: all clean - -all: $(addprefix $(ROOT)/,$(addsuffix .done,$(TESTS))) $(addprefix $(ROOT)/,$(addsuffix _11.done,$(TESTS11))) $(addprefix $(ROOT)/,$(addsuffix _17.done,$(TESTS17))) $(addprefix $(ROOT)/,$(addsuffix _old.done,$(OLDABITESTS))) $(addprefix $(ROOT)/,$(addsuffix _libcpp.done,$(LIBCPPTESTS))) +all: $(addprefix $(ROOT)/,$(addsuffix .done,$(TESTS))) $(addprefix $(ROOT)/,$(addsuffix _11.done,$(TESTS11))) $(addprefix $(ROOT)/,$(addsuffix _17.done,$(TESTS17))) $(addprefix $(ROOT)/,$(addsuffix _old.done,$(OLDABITESTS))) # run C++98 tests -$(ROOT)/%.done : $(ROOT)/% +$(ROOT)/%.done: $(ROOT)/%$(DOTEXE) @echo Testing $* $(QUIET)$(TIMELIMIT)$(ROOT)/$* $(RUN_ARGS) @touch $@ # run C++11 tests -$(ROOT)/%_11.done : $(ROOT)/%_11 +$(ROOT)/%_11.done: $(ROOT)/%_11$(DOTEXE) @echo Testing $*_11 $(QUIET)$(TIMELIMIT)$(ROOT)/$*_11 $(RUN_ARGS) @touch $@ # run C++17 tests -$(ROOT)/%_17.done : $(ROOT)/%_17 +$(ROOT)/%_17.done: $(ROOT)/%_17$(DOTEXE) @echo Testing $*_17 $(QUIET)$(TIMELIMIT)$(ROOT)/$*_17 $(RUN_ARGS) @touch $@ # run libstdc++ _GLIBCXX_USE_CXX11_ABI=0 tests -$(ROOT)/%_old.done : $(ROOT)/%_old +$(ROOT)/%_old.done: $(ROOT)/%_old$(DOTEXE) @echo Testing $*_old $(QUIET)$(TIMELIMIT)$(ROOT)/$*_old $(RUN_ARGS) @touch $@ # build C++98 tests -$(ROOT)/%: $(SRC)/%.cpp $(SRC)/%_test.d - mkdir -p $(dir $@) - $(QUIET)$(DMD) $(DFLAGS) -extern-std=c++98 -main -unittest -version=CoreUnittest -c -of=$(ROOT)/$*_d.o $(SRC)/$*_test.d - $(QUIET)$(CXX) $(CXXFLAGS_BASE) -std=c++98 -o $@ $< $(ROOT)/$*_d.o $(DRUNTIME) -lpthread $(LDL) +$(ROOT)/%$(DOTEXE): $(SRC)/%.cpp $(SRC)/%_test.d + @mkdir -p $(dir $@) + $(QUIET)$(DMD) $(DFLAGS) -extern-std=c++98 -main -unittest -version=CoreUnittest -c -of=$(ROOT)/$*_d$(DOTOBJ) $(SRC)/$*_test.d + $(QUIET)$(CXX) $(CXXFLAGS_BASE) -std=c++98 -o $@ $< $(ROOT)/$*_d$(DOTOBJ) $(DRUNTIME) -lpthread $(LDL) # build C++11 tests -$(ROOT)/%_11: $(SRC)/%.cpp $(SRC)/%_test.d - mkdir -p $(dir $@) - $(QUIET)$(DMD) $(DFLAGS) -extern-std=c++11 -main -unittest -version=CoreUnittest -c -of=$(ROOT)/$*_11_d.o $(SRC)/$*_test.d - $(QUIET)$(CXX) $(CXXFLAGS_BASE) -std=c++11 -o $@ $< $(ROOT)/$*_11_d.o $(DRUNTIME) -lpthread $(LDL) +$(ROOT)/%_11$(DOTEXE): $(SRC)/%.cpp $(SRC)/%_test.d + @mkdir -p $(dir $@) + $(QUIET)$(DMD) $(DFLAGS) -extern-std=c++11 -main -unittest -version=CoreUnittest -c -of=$(ROOT)/$*_11_d$(DOTOBJ) $(SRC)/$*_test.d + $(QUIET)$(CXX) $(CXXFLAGS_BASE) -std=c++11 -o $@ $< $(ROOT)/$*_11_d$(DOTOBJ) $(DRUNTIME) -lpthread $(LDL) # build C++17 tests -$(ROOT)/%_17: $(SRC)/%.cpp $(SRC)/%_test.d - mkdir -p $(dir $@) - $(QUIET)$(DMD) $(DFLAGS) -extern-std=c++17 -main -unittest -version=CoreUnittest -c -of=$(ROOT)/$*_17_d.o $(SRC)/$*_test.d - $(QUIET)$(CXX) $(CXXFLAGS_BASE) -std=c++17 -o $@ $< $(ROOT)/$*_17_d.o $(DRUNTIME) -lpthread $(LDL) +$(ROOT)/%_17$(DOTEXE): $(SRC)/%.cpp $(SRC)/%_test.d + @mkdir -p $(dir $@) + $(QUIET)$(DMD) $(DFLAGS) -extern-std=c++17 -main -unittest -version=CoreUnittest -c -of=$(ROOT)/$*_17_d$(DOTOBJ) $(SRC)/$*_test.d + $(QUIET)$(CXX) $(CXXFLAGS_BASE) -std=c++17 -o $@ $< $(ROOT)/$*_17_d$(DOTOBJ) $(DRUNTIME) -lpthread $(LDL) # build libstdc++ _GLIBCXX_USE_CXX11_ABI=0 tests -$(ROOT)/%_old: $(SRC)/%.cpp $(SRC)/%_test.d - mkdir -p $(dir $@) - $(QUIET)$(DMD) $(DFLAGS) -version=_GLIBCXX_USE_CXX98_ABI -main -unittest -version=CoreUnittest -c -of=$(ROOT)/$*_old_d.o $(SRC)/$*_test.d - $(QUIET)$(CXX) $(CXXFLAGS_BASE) -D_GLIBCXX_USE_CXX11_ABI=0 -o $@ $< $(ROOT)/$*_old_d.o $(DRUNTIME) -lpthread $(LDL) +$(ROOT)/%_old$(DOTEXE): $(SRC)/%.cpp $(SRC)/%_test.d + @mkdir -p $(dir $@) + $(QUIET)$(DMD) $(DFLAGS) -version=_GLIBCXX_USE_CXX98_ABI -main -unittest -version=CoreUnittest -c -of=$(ROOT)/$*_old_d$(DOTOBJ) $(SRC)/$*_test.d + $(QUIET)$(CXX) $(CXXFLAGS_BASE) -D_GLIBCXX_USE_CXX11_ABI=0 -o $@ $< $(ROOT)/$*_old_d$(DOTOBJ) $(DRUNTIME) -lpthread $(LDL) + +endif # end Posix clean: rm -rf $(GENERATED) diff --git a/runtime/druntime/test/stdcpp/msc_ver.c b/runtime/druntime/test/stdcpp/msc_ver.c new file mode 100644 index 00000000000..e390e3ba6bd --- /dev/null +++ b/runtime/druntime/test/stdcpp/msc_ver.c @@ -0,0 +1 @@ +_MSC_VER diff --git a/runtime/druntime/test/stdcpp/win64.mak b/runtime/druntime/test/stdcpp/win64.mak deleted file mode 100644 index 04acee2e17a..00000000000 --- a/runtime/druntime/test/stdcpp/win64.mak +++ /dev/null @@ -1,38 +0,0 @@ -# built from the druntime top-level folder -# to be overwritten by caller -DMD=dmd -MODEL=64 -DRUNTIMELIB=druntime64.lib -CC=cl - -TESTS=array allocator memory new string utility vector - -_MSC_VER=$(file < ..\..\ver.txt) -ADD_CFLAGS=$(file < ..\..\cflags.txt) -ADD_DFLAGS=$(file < ..\..\dflags.txt) -ADD_TESTS=$(file < ..\..\add_tests.txt) - -TESTS=$(TESTS) $(ADD_TESTS) - -test: $(TESTS) - -$(TESTS): - "$(CC)" -c /Fo$@_cpp.obj test\stdcpp\src\$@.cpp /EHsc /MT $(ADD_CFLAGS) - "$(DMD)" -of=$@.exe -m$(MODEL) -conf= -Iimport -defaultlib=$(DRUNTIMELIB) -main -unittest -version=CoreUnittest -version=_MSC_VER_$(_MSC_VER) -mscrtlib=libcmt $(ADD_DFLAGS) test\stdcpp\src\$@_test.d $@_cpp.obj - $@.exe - del $@.exe $@.obj $@_cpp.obj - - "$(CC)" -c /Fo$@_cpp.obj test\stdcpp\src\$@.cpp /EHsc /MD $(ADD_CFLAGS) - "$(DMD)" -of=$@.exe -m$(MODEL) -conf= -Iimport -defaultlib=$(DRUNTIMELIB) -main -unittest -version=CoreUnittest -version=_MSC_VER_$(_MSC_VER) -mscrtlib=msvcrt $(ADD_DFLAGS) test\stdcpp\src\$@_test.d $@_cpp.obj - $@.exe - del $@.exe $@.obj $@_cpp.obj - - "$(CC)" -c /Fo$@_cpp.obj test\stdcpp\src\$@.cpp /EHsc /MTd $(ADD_CFLAGS) - "$(DMD)" -of=$@.exe -m$(MODEL) -conf= -Iimport -defaultlib=$(DRUNTIMELIB) -main -unittest -version=CoreUnittest -version=_MSC_VER_$(_MSC_VER) -mscrtlib=libcmtd $(ADD_DFLAGS) test\stdcpp\src\$@_test.d $@_cpp.obj - $@.exe - del $@.exe $@.obj $@_cpp.obj - - "$(CC)" -c /Fo$@_cpp.obj test\stdcpp\src\$@.cpp /EHsc /MDd $(ADD_CFLAGS) - "$(DMD)" -of=$@.exe -m$(MODEL) -conf= -Iimport -defaultlib=$(DRUNTIMELIB) -main -unittest -version=CoreUnittest -version=_MSC_VER_$(_MSC_VER) -mscrtlib=msvcrtd $(ADD_DFLAGS) test\stdcpp\src\$@_test.d $@_cpp.obj - $@.exe - del $@.exe $@.obj $@_cpp.obj From e8daddb7838eef091514f428826e8e75879bc0a9 Mon Sep 17 00:00:00 2001 From: Martin Kinkelin Date: Sun, 10 Dec 2023 04:14:08 +0100 Subject: [PATCH 123/215] druntime: Merge test/shared/win64.mak into Makefile --- runtime/druntime/Makefile | 11 +++- runtime/druntime/test/shared/Makefile | 85 ++++++++++++++++++-------- runtime/druntime/test/shared/win64.mak | 31 ---------- 3 files changed, 70 insertions(+), 57 deletions(-) delete mode 100644 runtime/druntime/test/shared/win64.mak diff --git a/runtime/druntime/Makefile b/runtime/druntime/Makefile index 74682f25408..16631905280 100644 --- a/runtime/druntime/Makefile +++ b/runtime/druntime/Makefile @@ -419,7 +419,12 @@ ifeq ($(HAS_ADDITIONAL_TESTS),1) ifneq (32omf,$(MODEL)) ADDITIONAL_TESTS+=test/stdcpp endif - ADDITIONAL_TESTS+=$(if $(SHARED),test/shared,) + ifneq (,$(SHARED)) + ADDITIONAL_TESTS+=test/shared + else ifeq (windows,$(OS)) + # although a druntime DLL isn't supported yet, there are Windows-specific general DLL tests + ADDITIONAL_TESTS+=test/shared + endif endif .PHONY : unittest @@ -481,8 +486,12 @@ $(ROOT)/unittest/% : $(ROOT)/unittest/test_runner$(DOTEXE) # succeeded, render the file new again @touch $@ +ifeq (,$(SHARED)) +$(addsuffix /.run,$(ADDITIONAL_TESTS)): $(DRUNTIME) +else $(addsuffix /.run,$(filter-out test/shared,$(ADDITIONAL_TESTS))): $(DRUNTIME) test/shared/.run: $(DRUNTIMESO) +endif test/%/.run: test/%/Makefile $(DMD) $(QUIET)$(MAKE) -C test/$* MODEL=$(MODEL) OS=$(OS) DMD=$(abspath $(DMD)) BUILD=$(BUILD) \ diff --git a/runtime/druntime/test/shared/Makefile b/runtime/druntime/test/shared/Makefile index a2acdc8dcf9..78103cfd6bb 100644 --- a/runtime/druntime/test/shared/Makefile +++ b/runtime/druntime/test/shared/Makefile @@ -1,73 +1,108 @@ -LINK_SHARED:=1 +# druntime DLL not supported on Windows yet +LINK_SHARED:=$(if $(findstring $(OS),windows),,1) include ../common.mak # affected by LINK_SHARED! +.PHONY: all clean + +ifeq (windows,$(OS)) + +TESTS:=loadlibwin dllrefcount dllgc dynamiccast + +all: $(addprefix $(ROOT)/,$(TESTS)) + +$(ROOT)/dllrefcount: $(SRC)/dllrefcount.d + @echo Testing dllrefcount + $(QUIET)$(DMD) $(DFLAGS) -run $< + +$(ROOT)/loadlibwin: $(SRC)/loadlibwin.d + @echo Testing loadlibwin + $(QUIET)$(DMD) $(DFLAGS) -run $< + +$(ROOT)/dllgc: $(SRC)/dllgc.d + @echo Testing dllgc + $(QUIET)$(DMD) $(DFLAGS) -version=DLL -shared -of$(ROOT)/dllgc$(DOTDLL) $< + $(QUIET)$(DMD) $(DFLAGS) -of$(ROOT)/loaddllgc$(DOTEXE) $< + $(QUIET)$(ROOT)/loaddllgc + +$(ROOT)/dynamiccast: $(SRC)/dynamiccast.d + @echo Testing dynamiccast + $(QUIET)$(DMD) $(DFLAGS) -version=DLL -shared -of$(ROOT)/dynamiccast$(DOTDLL) $< + $(QUIET)$(DMD) $(DFLAGS) -of$(ROOT)/dynamiccast$(DOTEXE) $< + $(QUIET)rm -f $(ROOT)/dynamiccast_end{bar,main} + $(QUIET)$(ROOT)/dynamiccast + $(QUIET)test -f $(ROOT)/dynamiccast_endbar + $(QUIET)test -f $(ROOT)/dynamiccast_endmain + +else # Posix: + TESTS:=link load linkD linkDR loadDR host finalize dynamiccast TESTS+=link_linkdep load_linkdep link_loaddep load_loaddep load_13414 EXPORT_DYNAMIC=$(if $(findstring $(OS),linux freebsd dragonflybsd),-L--export-dynamic,) NO_AS_NEEDED=$(if $(findstring $(OS),linux freebsd dragonflybsd),-L--no-as-needed,) -.PHONY: all clean all: $(addprefix $(ROOT)/,$(addsuffix .done,$(TESTS))) $(ROOT)/loadDR.done $(ROOT)/host.done: RUN_ARGS:=$(DRUNTIMESO) -$(ROOT)/dynamiccast.done: CLEANUP:=rm $(ROOT)/dynamiccast_endmain $(ROOT)/dynamiccast_endbar +$(ROOT)/dynamiccast.done: CLEANUP:=rm $(ROOT)/dynamiccast_endmain$(DOTEXE) $(ROOT)/dynamiccast_endbar$(DOTEXE) -$(ROOT)/%.done: $(ROOT)/% +$(ROOT)/%.done: $(ROOT)/%$(DOTEXE) @echo Testing $* $(QUIET)$(TIMELIMIT)$< $(RUN_ARGS) $(CLEANUP) @touch $@ -$(ROOT)/link: $(SRC)/link.d $(ROOT)/lib.so $(DRUNTIMESO) - $(QUIET)$(DMD) $(DFLAGS) -of$@ $< -L$(ROOT)/lib.so +$(ROOT)/link$(DOTEXE): $(SRC)/link.d $(ROOT)/lib$(DOTDLL) $(DRUNTIMESO) + $(QUIET)$(DMD) $(DFLAGS) -of$@ $< -L$(ROOT)/lib$(DOTDLL) -$(ROOT)/link_linkdep: $(SRC)/link_linkdep.d $(ROOT)/lib.so $(ROOT)/liblinkdep.so $(DRUNTIMESO) - $(QUIET)$(DMD) $(DFLAGS) -of$@ $< $(LINKFLAGS) -L$(ROOT)/liblinkdep.so -L$(ROOT)/lib.so +$(ROOT)/link_linkdep$(DOTEXE): $(SRC)/link_linkdep.d $(ROOT)/lib$(DOTDLL) $(ROOT)/liblinkdep$(DOTDLL) $(DRUNTIMESO) + $(QUIET)$(DMD) $(DFLAGS) -of$@ $< $(LINKFLAGS) -L$(ROOT)/liblinkdep$(DOTDLL) -L$(ROOT)/lib$(DOTDLL) -$(ROOT)/load_linkdep: $(SRC)/load_linkdep.d $(ROOT)/lib.so $(ROOT)/liblinkdep.so $(DRUNTIMESO) +$(ROOT)/load_linkdep$(DOTEXE): $(SRC)/load_linkdep.d $(ROOT)/lib$(DOTDLL) $(ROOT)/liblinkdep$(DOTDLL) $(DRUNTIMESO) $(QUIET)$(DMD) $(DFLAGS) -of$@ $< $(LINKFLAGS) $(LINKDL) -$(ROOT)/link_loaddep: $(SRC)/link_loaddep.d $(ROOT)/lib.so $(ROOT)/libloaddep.so $(DRUNTIMESO) - $(QUIET)$(DMD) $(DFLAGS) -of$@ $< $(LINKFLAGS) -L$(ROOT)/libloaddep.so +$(ROOT)/link_loaddep$(DOTEXE): $(SRC)/link_loaddep.d $(ROOT)/lib$(DOTDLL) $(ROOT)/libloaddep$(DOTDLL) $(DRUNTIMESO) + $(QUIET)$(DMD) $(DFLAGS) -of$@ $< $(LINKFLAGS) -L$(ROOT)/libloaddep$(DOTDLL) -$(ROOT)/load_loaddep: $(SRC)/load_loaddep.d $(ROOT)/lib.so $(ROOT)/libloaddep.so $(DRUNTIMESO) +$(ROOT)/load_loaddep$(DOTEXE): $(SRC)/load_loaddep.d $(ROOT)/lib$(DOTDLL) $(ROOT)/libloaddep$(DOTDLL) $(DRUNTIMESO) $(QUIET)$(DMD) $(DFLAGS) -of$@ $< $(LINKFLAGS) $(LINKDL) -$(ROOT)/load $(ROOT)/finalize: $(ROOT)/%: $(SRC)/%.d $(ROOT)/lib.so $(DRUNTIMESO) +$(ROOT)/load$(DOTEXE) $(ROOT)/finalize$(DOTEXE): $(ROOT)/%$(DOTEXE): $(SRC)/%.d $(ROOT)/lib$(DOTDLL) $(DRUNTIMESO) $(QUIET)$(DMD) $(DFLAGS) -of$@ $< $(LINKDL) -$(ROOT)/load_13414: $(ROOT)/%: $(SRC)/%.d $(ROOT)/lib_13414.so $(DRUNTIMESO) +$(ROOT)/load_13414$(DOTEXE): $(ROOT)/%$(DOTEXE): $(SRC)/%.d $(ROOT)/lib_13414$(DOTDLL) $(DRUNTIMESO) $(QUIET)$(DMD) $(DFLAGS) -of$@ $< $(LINKDL) -$(ROOT)/dynamiccast: $(SRC)/dynamiccast.d $(ROOT)/dynamiccast.so $(DRUNTIMESO) +$(ROOT)/dynamiccast$(DOTEXE): $(SRC)/dynamiccast.d $(ROOT)/dynamiccast$(DOTDLL) $(DRUNTIMESO) $(QUIET)$(DMD) $(DFLAGS) -of$@ $(SRC)/dynamiccast.d $(LINKDL) -$(ROOT)/dynamiccast.so: $(SRC)/dynamiccast.d $(DRUNTIMESO) +$(ROOT)/dynamiccast$(DOTDLL): $(SRC)/dynamiccast.d $(DRUNTIMESO) $(QUIET)$(DMD) $(DFLAGS) -of$@ $< -version=DLL -fPIC -shared $(LINKDL) -$(ROOT)/linkD: $(SRC)/linkD.c $(ROOT)/lib.so $(DRUNTIMESO) - $(QUIET)$(CC) $(CFLAGS) -o $@ $< $(ROOT)/lib.so $(LDL) -pthread +$(ROOT)/linkD$(DOTEXE): $(SRC)/linkD.c $(ROOT)/lib$(DOTDLL) $(DRUNTIMESO) + $(QUIET)$(CC) $(CFLAGS) -o $@ $< $(ROOT)/lib$(DOTDLL) $(LDL) -pthread -$(ROOT)/linkDR: $(SRC)/linkDR.c $(ROOT)/lib.so $(DRUNTIMESO) +$(ROOT)/linkDR$(DOTEXE): $(SRC)/linkDR.c $(ROOT)/lib$(DOTDLL) $(DRUNTIMESO) $(QUIET)$(CC) $(CFLAGS) -o $@ $< $(DRUNTIMESO) $(LDL) -pthread -$(ROOT)/loadDR: $(SRC)/loadDR.c $(ROOT)/lib.so $(DRUNTIMESO) +$(ROOT)/loadDR$(DOTEXE): $(SRC)/loadDR.c $(ROOT)/lib$(DOTDLL) $(DRUNTIMESO) $(QUIET)$(CC) $(CFLAGS) -o $@ $< $(LDL) -pthread -$(ROOT)/host: $(SRC)/host.c $(ROOT)/plugin1.so $(ROOT)/plugin2.so +$(ROOT)/host$(DOTEXE): $(SRC)/host.c $(ROOT)/plugin1$(DOTDLL) $(ROOT)/plugin2$(DOTDLL) $(QUIET)$(CC) $(CFLAGS) -o $@ $< $(LDL) -pthread -$(ROOT)/liblinkdep.so: $(ROOT)/lib.so -$(ROOT)/liblinkdep.so: DFLAGS+=-L$(ROOT)/lib.so +$(ROOT)/liblinkdep$(DOTDLL): $(ROOT)/lib$(DOTDLL) +$(ROOT)/liblinkdep$(DOTDLL): DFLAGS+=-L$(ROOT)/lib$(DOTDLL) -$(ROOT)/plugin1.so $(ROOT)/plugin2.so: $(SRC)/plugin.d $(DRUNTIMESO) +$(ROOT)/plugin1$(DOTDLL) $(ROOT)/plugin2$(DOTDLL): $(SRC)/plugin.d $(DRUNTIMESO) $(QUIET)$(DMD) -fPIC -shared $(DFLAGS) -of$@ $< -$(ROOT)/%.so: $(SRC)/%.d $(DRUNTIMESO) +$(ROOT)/%$(DOTDLL): $(SRC)/%.d $(DRUNTIMESO) $(QUIET)$(DMD) -fPIC -shared $(DFLAGS) -of$@ $< $(LINKDL) +endif # end Posix + clean: rm -rf $(GENERATED) diff --git a/runtime/druntime/test/shared/win64.mak b/runtime/druntime/test/shared/win64.mak deleted file mode 100644 index 878ea636929..00000000000 --- a/runtime/druntime/test/shared/win64.mak +++ /dev/null @@ -1,31 +0,0 @@ -# built from the druntime top-level folder -# to be overwritten by caller -DMD=dmd -MODEL=64 -DRUNTIMELIB=druntime64.lib - -test: loadlibwin dllrefcount dllgc dynamiccast - -dllrefcount: - $(DMD) -g -m$(MODEL) -conf= -Iimport -defaultlib=$(DRUNTIMELIB) test\shared\src\dllrefcount.d - dllrefcount.exe - del dllrefcount.exe dllrefcount.obj - -loadlibwin: - $(DMD) -g -m$(MODEL) -conf= -Iimport -defaultlib=$(DRUNTIMELIB) test\shared\src\loadlibwin.d - loadlibwin.exe - del loadlibwin.exe loadlibwin.obj - -dllgc: - $(DMD) -g -m$(MODEL) -conf= -Iimport -defaultlib=$(DRUNTIMELIB) -version=DLL -shared -ofdllgc.dll test\shared\src\dllgc.d - $(DMD) -g -m$(MODEL) -conf= -Iimport -defaultlib=$(DRUNTIMELIB) -ofloaddllgc.exe test\shared\src\dllgc.d - loaddllgc.exe - del loaddllgc.exe loaddllgc.obj dllgc.dll dllgc.obj - -dynamiccast: - $(DMD) -g -m$(MODEL) -conf= -Iimport -defaultlib=$(DRUNTIMELIB) -version=DLL -shared -ofdynamiccast.dll test\shared\src\dynamiccast.d - $(DMD) -g -m$(MODEL) -conf= -Iimport -defaultlib=$(DRUNTIMELIB) -ofdynamiccast.exe test\shared\src\dynamiccast.d - dynamiccast.exe - cmd /c "if not exist dynamiccast_endbar exit 1" - cmd /c "if not exist dynamiccast_endmain exit 1" - del dynamiccast.exe dynamiccast.dll dynamiccast.obj dynamiccast_endbar dynamiccast_endmain From e8cfb7e0bca485463598bc02276c6693de0def56 Mon Sep 17 00:00:00 2001 From: Martin Kinkelin Date: Sun, 10 Dec 2023 05:54:38 +0100 Subject: [PATCH 124/215] druntime: Disable additional tests on Windows OMF too --- runtime/druntime/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/runtime/druntime/Makefile b/runtime/druntime/Makefile index 16631905280..656b2545ed1 100644 --- a/runtime/druntime/Makefile +++ b/runtime/druntime/Makefile @@ -430,7 +430,7 @@ endif .PHONY : unittest ifeq (1,$(BUILD_WAS_SPECIFIED)) ifeq (32omf,$(MODEL)) -unittest : $(addsuffix /.run,$(ADDITIONAL_TESTS)) +unittest : @echo "Skipping druntime unittests because they cannot be linked on Win32 + OMF due to OPTLINK issues." else unittest : $(UT_MODULES) $(addsuffix /.run,$(ADDITIONAL_TESTS)) From 415292fe2a95a93a5ac2462ab41b3fd0247a99b4 Mon Sep 17 00:00:00 2001 From: Martin Kinkelin Date: Sun, 10 Dec 2023 18:20:21 +0100 Subject: [PATCH 125/215] druntime: Slightly simplify test/{uuid,valgrind} Makefiles By disabling them in druntime/Makefile on unsupported platforms. --- runtime/druntime/Makefile | 11 ++++++----- runtime/druntime/test/stdcpp/Makefile | 2 +- runtime/druntime/test/uuid/Makefile | 13 ------------- runtime/druntime/test/valgrind/Makefile | 7 +------ 4 files changed, 8 insertions(+), 25 deletions(-) diff --git a/runtime/druntime/Makefile b/runtime/druntime/Makefile index 656b2545ed1..4061b8693f1 100644 --- a/runtime/druntime/Makefile +++ b/runtime/druntime/Makefile @@ -414,17 +414,18 @@ HAS_ADDITIONAL_TESTS:=$(shell test -d test && echo 1) ifeq ($(HAS_ADDITIONAL_TESTS),1) ADDITIONAL_TESTS:=test/init_fini test/exceptions test/coverage test/profile test/cycles test/allocations test/typeinfo \ test/aa test/cpuid test/gc test/hash test/lifetime \ - test/thread test/unittest test/imports test/betterc test/config \ - test/traits test/uuid test/valgrind - ifneq (32omf,$(MODEL)) - ADDITIONAL_TESTS+=test/stdcpp - endif + test/thread test/unittest test/imports test/betterc test/stdcpp test/config test/traits ifneq (,$(SHARED)) ADDITIONAL_TESTS+=test/shared else ifeq (windows,$(OS)) # although a druntime DLL isn't supported yet, there are Windows-specific general DLL tests ADDITIONAL_TESTS+=test/shared endif + ifeq (windows,$(OS)) + ADDITIONAL_TESTS+=test/uuid + else + ADDITIONAL_TESTS+=test/valgrind + endif endif .PHONY : unittest diff --git a/runtime/druntime/test/stdcpp/Makefile b/runtime/druntime/test/stdcpp/Makefile index f3c150bb33d..d4b15af1916 100644 --- a/runtime/druntime/test/stdcpp/Makefile +++ b/runtime/druntime/test/stdcpp/Makefile @@ -5,7 +5,7 @@ include ../common.mak ifeq (windows,$(OS)) CC:=cl -EXTRA_CXXFLAGS:=/EHsc +EXTRA_CXXFLAGS:=/nologo /EHsc EXTRA_DFLAGS:= TESTS:=allocator array memory new string utility vector diff --git a/runtime/druntime/test/uuid/Makefile b/runtime/druntime/test/uuid/Makefile index 9e6ffc926ee..0c52b8f273e 100644 --- a/runtime/druntime/test/uuid/Makefile +++ b/runtime/druntime/test/uuid/Makefile @@ -1,23 +1,10 @@ include ../common.mak -SUPPORTED:=0 -ifeq (windows,$(OS)) - ifneq (32omf,$(MODEL)) - SUPPORTED:=1 - endif -endif - .PHONY: all clean - -ifneq (1,$(SUPPORTED)) -all: - @echo "Skipping uuid test on platforms other than Windows MSVC" -else all: $(ROOT)/test$(DOTEXE) $(ROOT)/%$(DOTEXE): %.d $(QUIET)$(DMD) $(DFLAGS) -of$@ $< uuid.lib -endif clean: rm -rf $(ROOT) diff --git a/runtime/druntime/test/valgrind/Makefile b/runtime/druntime/test/valgrind/Makefile index 2967aff4deb..47f1792a986 100644 --- a/runtime/druntime/test/valgrind/Makefile +++ b/runtime/druntime/test/valgrind/Makefile @@ -1,11 +1,6 @@ include ../common.mak -ifeq (windows,$(OS)) - # no valgrind on Windows - TESTS:= -else - TESTS:=ok_append no_use_after_free no_oob no_oob_sentinel no_use_after_gc -endif +TESTS:=ok_append no_use_after_free no_oob no_oob_sentinel no_use_after_gc GC_SRC:= \ ../../src/core/internal/gc/impl/conservative/gc.d \ From a5d52af5c71d2248d39497d3a64bc5e75ae8ab59 Mon Sep 17 00:00:00 2001 From: Martin Kinkelin Date: Sun, 10 Dec 2023 23:07:14 +0100 Subject: [PATCH 126/215] druntime: Avoid `-run` in Windows-specific additional tests As temporary object files seem to collide for parallel runs in the same working dir. --- runtime/druntime/test/shared/Makefile | 40 +++++++++++++++------------ runtime/druntime/test/stdcpp/Makefile | 12 +++++--- 2 files changed, 30 insertions(+), 22 deletions(-) diff --git a/runtime/druntime/test/shared/Makefile b/runtime/druntime/test/shared/Makefile index 78103cfd6bb..94cdbd6b2e7 100644 --- a/runtime/druntime/test/shared/Makefile +++ b/runtime/druntime/test/shared/Makefile @@ -9,30 +9,34 @@ ifeq (windows,$(OS)) TESTS:=loadlibwin dllrefcount dllgc dynamiccast -all: $(addprefix $(ROOT)/,$(TESTS)) +all: $(addprefix $(ROOT)/,$(addsuffix .done,$(TESTS))) + +$(ROOT)/%.done: $(ROOT)/%$(DOTEXE) + @echo Testing $* + $(QUIET)$(TIMELIMIT)$< $(RUN_ARGS) + @touch $@ + +$(ROOT)/dynamiccast.done: $(ROOT)/%.done: $(ROOT)/%$(DOTEXE) + @echo Testing $* + $(QUIET)rm -f $(ROOT)/dynamiccast_end{bar,main} + $(QUIET)$(TIMELIMIT)$< $(RUN_ARGS) + $(QUIET)test -f $(ROOT)/dynamiccast_endbar + $(QUIET)test -f $(ROOT)/dynamiccast_endmain + @touch $@ -$(ROOT)/dllrefcount: $(SRC)/dllrefcount.d - @echo Testing dllrefcount - $(QUIET)$(DMD) $(DFLAGS) -run $< +$(ROOT)/dllrefcount$(DOTEXE): $(SRC)/dllrefcount.d + $(QUIET)$(DMD) $(DFLAGS) -of$@ $< -$(ROOT)/loadlibwin: $(SRC)/loadlibwin.d - @echo Testing loadlibwin - $(QUIET)$(DMD) $(DFLAGS) -run $< +$(ROOT)/loadlibwin$(DOTEXE): $(SRC)/loadlibwin.d + $(QUIET)$(DMD) $(DFLAGS) -of$@ $< -$(ROOT)/dllgc: $(SRC)/dllgc.d - @echo Testing dllgc +$(ROOT)/dllgc$(DOTEXE): $(SRC)/dllgc.d $(QUIET)$(DMD) $(DFLAGS) -version=DLL -shared -of$(ROOT)/dllgc$(DOTDLL) $< - $(QUIET)$(DMD) $(DFLAGS) -of$(ROOT)/loaddllgc$(DOTEXE) $< - $(QUIET)$(ROOT)/loaddllgc + $(QUIET)$(DMD) $(DFLAGS) -of$@ $< -$(ROOT)/dynamiccast: $(SRC)/dynamiccast.d - @echo Testing dynamiccast +$(ROOT)/dynamiccast$(DOTEXE): $(SRC)/dynamiccast.d $(QUIET)$(DMD) $(DFLAGS) -version=DLL -shared -of$(ROOT)/dynamiccast$(DOTDLL) $< - $(QUIET)$(DMD) $(DFLAGS) -of$(ROOT)/dynamiccast$(DOTEXE) $< - $(QUIET)rm -f $(ROOT)/dynamiccast_end{bar,main} - $(QUIET)$(ROOT)/dynamiccast - $(QUIET)test -f $(ROOT)/dynamiccast_endbar - $(QUIET)test -f $(ROOT)/dynamiccast_endmain + $(QUIET)$(DMD) $(DFLAGS) -of$@ $< else # Posix: diff --git a/runtime/druntime/test/stdcpp/Makefile b/runtime/druntime/test/stdcpp/Makefile index d4b15af1916..0aea85c80fa 100644 --- a/runtime/druntime/test/stdcpp/Makefile +++ b/runtime/druntime/test/stdcpp/Makefile @@ -24,16 +24,20 @@ $(ROOT)/%: $(SRC)/%.cpp $(SRC)/%_test.d @mkdir -p $(dir $@) $(QUIET)$(CC) /MT $(EXTRA_CXXFLAGS) -c /Fo$@_cpp$(DOTOBJ) $< - $(QUIET)$(DMD) -mscrtlib=libcmt $(DFLAGS) $(EXTRA_DFLAGS) -main -unittest -version=CoreUnittest -version=_MSC_VER_$(MSC_VER) $@_cpp$(DOTOBJ) -run $(SRC)/$*_test.d + $(QUIET)$(DMD) -mscrtlib=libcmt $(DFLAGS) $(EXTRA_DFLAGS) -main -unittest -version=CoreUnittest -version=_MSC_VER_$(MSC_VER) -of$@$(DOTEXE) $@_cpp$(DOTOBJ) $(SRC)/$*_test.d + $(QUIET)$(TIMELIMIT)$@ $(RUN_ARGS) $(QUIET)$(CC) /MD $(EXTRA_CXXFLAGS) -c /Fo$@_cpp$(DOTOBJ) $< - $(QUIET)$(DMD) -mscrtlib=msvcrt $(DFLAGS) $(EXTRA_DFLAGS) -main -unittest -version=CoreUnittest -version=_MSC_VER_$(MSC_VER) $@_cpp$(DOTOBJ) -run $(SRC)/$*_test.d + $(QUIET)$(DMD) -mscrtlib=msvcrt $(DFLAGS) $(EXTRA_DFLAGS) -main -unittest -version=CoreUnittest -version=_MSC_VER_$(MSC_VER) -of$@$(DOTEXE) $@_cpp$(DOTOBJ) $(SRC)/$*_test.d + $(QUIET)$(TIMELIMIT)$@ $(RUN_ARGS) $(QUIET)$(CC) /MTd $(EXTRA_CXXFLAGS) -c /Fo$@_cpp$(DOTOBJ) $< - $(QUIET)$(DMD) -mscrtlib=libcmtd $(DFLAGS) $(EXTRA_DFLAGS) -main -unittest -version=CoreUnittest -version=_MSC_VER_$(MSC_VER) $@_cpp$(DOTOBJ) -run $(SRC)/$*_test.d + $(QUIET)$(DMD) -mscrtlib=libcmtd $(DFLAGS) $(EXTRA_DFLAGS) -main -unittest -version=CoreUnittest -version=_MSC_VER_$(MSC_VER) -of$@$(DOTEXE) $@_cpp$(DOTOBJ) $(SRC)/$*_test.d + $(QUIET)$(TIMELIMIT)$@ $(RUN_ARGS) $(QUIET)$(CC) /MDd $(EXTRA_CXXFLAGS) -c /Fo$@_cpp$(DOTOBJ) $< - $(QUIET)$(DMD) -mscrtlib=msvcrtd $(DFLAGS) $(EXTRA_DFLAGS) -main -unittest -version=CoreUnittest -version=_MSC_VER_$(MSC_VER) $@_cpp$(DOTOBJ) -run $(SRC)/$*_test.d + $(QUIET)$(DMD) -mscrtlib=msvcrtd $(DFLAGS) $(EXTRA_DFLAGS) -main -unittest -version=CoreUnittest -version=_MSC_VER_$(MSC_VER) -of$@$(DOTEXE) $@_cpp$(DOTOBJ) $(SRC)/$*_test.d + $(QUIET)$(TIMELIMIT)$@ $(RUN_ARGS) else # Posix: From be5ba1742d016fcda5efea80bec12d4ae29dd17f Mon Sep 17 00:00:00 2001 From: Martin Kinkelin Date: Tue, 12 Dec 2023 02:21:14 +0100 Subject: [PATCH 127/215] Makefile: Include druntime in install target --- runtime/druntime/Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/runtime/druntime/Makefile b/runtime/druntime/Makefile index 4061b8693f1..52305292eb6 100644 --- a/runtime/druntime/Makefile +++ b/runtime/druntime/Makefile @@ -543,8 +543,8 @@ install: echo "Darwin_64_32_disabled" else install: target - mkdir -p $(INSTALL_DIR)/src/druntime/import - cp -r import/* $(INSTALL_DIR)/src/druntime/import/ + mkdir -p '$(INSTALL_DIR)'/src/druntime/import + cp -r import/* '$(INSTALL_DIR)'/src/druntime/import/ endif clean: $(addsuffix /.clean,$(ADDITIONAL_TESTS)) From c15a6fe0986bd76da299fae93b1b9a8eec1114d5 Mon Sep 17 00:00:00 2001 From: Martin Kinkelin Date: Fri, 15 Dec 2023 02:19:15 +0100 Subject: [PATCH 128/215] druntime Makefile: Handle DMD set as absolute path, and fix up remaining posix.mak occurrences --- runtime/druntime/Makefile | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/runtime/druntime/Makefile b/runtime/druntime/Makefile index 52305292eb6..361d0eb5c0c 100644 --- a/runtime/druntime/Makefile +++ b/runtime/druntime/Makefile @@ -358,7 +358,7 @@ $(DMD_DIR)/../generated/$(OS)/$(BUILD)/$(MODEL)/dmd$(DOTEXE): $(MAKE) -C $(DMD_DIR)/.. dmd BUILD=$(BUILD) OS=$(OS) MODEL=$(MODEL) DMD="" # alias using the absolute path (the Phobos Makefile specifies an absolute path) -$(abspath $(DMD_DIR)/../generated/$(OS)/$(BUILD)/$(MODEL)/dmd): $(DMD_DIR)/../generated/$(OS)/$(BUILD)/$(MODEL)/dmd +$(abspath $(DMD_DIR)/../generated/$(OS)/$(BUILD)/$(MODEL)/dmd$(DOTEXE)): $(DMD_DIR)/../generated/$(OS)/$(BUILD)/$(MODEL)/dmd$(DOTEXE) ################### C/ASM Targets ############################ @@ -575,12 +575,12 @@ test_extractor: $(TESTS_EXTRACTOR) # # Extract @betterC tests of a module and run them in -betterC # -# make -f betterc -j20 # all tests -# make -f posix.mak src/core/memory.betterc # individual module +# make betterc -j20 # all tests +# make src/core/memory.betterc # individual module ################################################################################ betterc: | $(TESTS_EXTRACTOR) $(BETTERCTESTS_DIR)/.directory - $(MAKE) -f posix.mak $$(find src -type f -name '*.d' | sed 's/[.]d/.betterc/') + $(MAKE) $$(find src -type f -name '*.d' | sed 's/[.]d/.betterc/') %.betterc: %.d | $(TESTS_EXTRACTOR) $(BETTERCTESTS_DIR)/.directory @$(TESTS_EXTRACTOR) --betterC --attributes betterC \ @@ -614,7 +614,7 @@ publictests: $(addsuffix .publictests, $(basename $(SRCS))) ################################################################################ # Extract public tests of a module and test them in an separate file (i.e. without its module) # This is done to check for potentially missing imports in the examples, e.g. -# make -f posix.mak src/core/time.publictests +# make src/core/time.publictests ################################################################################ %.publictests: %.d $(TESTS_EXTRACTOR) $(DRUNTIME) | $(PUBLICTESTS_DIR)/.directory @$(TESTS_EXTRACTOR) --inputdir $< --outputdir $(PUBLICTESTS_DIR) From 38f60e0e79da4b14961ae2243db639ec2b3d4532 Mon Sep 17 00:00:00 2001 From: Martin Kinkelin Date: Fri, 15 Dec 2023 23:13:23 +0100 Subject: [PATCH 129/215] Makefiles: Add comments wrt. usage on Windows and a few example invocations --- runtime/druntime/Makefile | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/runtime/druntime/Makefile b/runtime/druntime/Makefile index 361d0eb5c0c..ed69d01670e 100644 --- a/runtime/druntime/Makefile +++ b/runtime/druntime/Makefile @@ -1,7 +1,17 @@ # This makefile is designed to be run by gnu make. -# The default make program on FreeBSD 8.1 is not gnu make; to install gnu make: -# pkg_add -r gmake -# and then run as gmake rather than make. +# - Windows: you may download a prebuilt zipped .exe from https://github.com/dlang/dmd/releases/download/nightly/gnumake-4.4-win64.zip. +# You also need a Git for Windows installation, for bash and common GNU tools like cp,mkdir,mv,rm,touch,which. +# - FreeBSD: the default make program on FreeBSD is not gnu make; to install gnu make: +# pkg install gmake +# and then run as gmake rather than make. +# +# Examples: +# - Build druntime: +# make -j$(nproc) +# - Build and run druntime tests: +# make -j$(nproc) unittest +# - Build and run druntime tests in debug mode only: +# make -j$(nproc) unittest-debug QUIET:= From cb2eaeaf57dbb98efd3a6ebcf70b0807b23c68d2 Mon Sep 17 00:00:00 2001 From: Martin Kinkelin Date: Wed, 13 Dec 2023 23:08:56 +0100 Subject: [PATCH 130/215] CI: Adapt to generic Makefile for Phobos --- dmd/mars.d | 2 ++ 1 file changed, 2 insertions(+) diff --git a/dmd/mars.d b/dmd/mars.d index a74fcec3cbb..6f87beeb383 100644 --- a/dmd/mars.d +++ b/dmd/mars.d @@ -375,6 +375,8 @@ void setDefaultLibrary(ref Param params, const ref Target target) if (driverParams.debuglibname is null) driverParams.debuglibname = driverParams.defaultlibname; + else if (!driverParams.debuglibname.length) // if `-debuglib=` (i.e. an empty debuglib) + driverParams.debuglibname = null; } void printPredefinedVersions(FILE* stream) From 909d1d18859d51a7b8597dd54874ceb151a8d542 Mon Sep 17 00:00:00 2001 From: Walter Bright Date: Tue, 19 Dec 2023 06:33:10 -0800 Subject: [PATCH 131/215] fix Issue 23411 - ImportC: undefined identifier __builtin_nanf (dlang/dmd!15918) --- runtime/druntime/src/__builtins.di | 4 ++++ tests/dmd/compilable/stdcheaders.c | 1 + 2 files changed, 5 insertions(+) diff --git a/runtime/druntime/src/__builtins.di b/runtime/druntime/src/__builtins.di index 74147a095cd..b4fef091b5f 100644 --- a/runtime/druntime/src/__builtins.di +++ b/runtime/druntime/src/__builtins.di @@ -53,6 +53,10 @@ version (CRuntime_Microsoft) version (DigitalMars) { + immutable float __nan = float.nan; + + float __builtin_nanf()(char*) { return float.nan; } + double __builtin_inf()() { return double.infinity; } float __builtin_inff()() { return float.infinity; } real __builtin_infl()() { return real.infinity; } diff --git a/tests/dmd/compilable/stdcheaders.c b/tests/dmd/compilable/stdcheaders.c index d89bf72fff6..a1a4dc7ffb4 100644 --- a/tests/dmd/compilable/stdcheaders.c +++ b/tests/dmd/compilable/stdcheaders.c @@ -23,6 +23,7 @@ #ifndef __APPLE__ // /Applications/Xcode-14.2.0.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/tgmath.h(39): Error: named parameter required before `...` #include +float x = NAN; #endif #ifndef _MSC_VER // setjmp.h(51): Error: missing tag `identifier` after `struct From ac227d3fc41846689a257700b14992f6af58272e Mon Sep 17 00:00:00 2001 From: Walter Bright Date: Tue, 19 Dec 2023 12:13:54 -0800 Subject: [PATCH 132/215] fix Issue 24283 - [SIMD][CODEGEN] Bad codegen with and not + AVX2 registers (dlang/dmd!15921) --- tests/dmd/runnable/testxmm2.d | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/tests/dmd/runnable/testxmm2.d b/tests/dmd/runnable/testxmm2.d index 67bee63ee8b..0b3a78d7792 100644 --- a/tests/dmd/runnable/testxmm2.d +++ b/tests/dmd/runnable/testxmm2.d @@ -5,6 +5,7 @@ version (D_SIMD) { import core.simd; +import core.stdc.stdio; import core.stdc.string; alias TypeTuple(T...) = T; @@ -283,6 +284,31 @@ void testdbl() /*****************************************/ +version (none)//(D_AVX2) +{ +// https://issues.dlang.org/show_bug.cgi?id=24283 + +import core.simd; +import core.stdc.stdio; + +void test24283() +{ + int8 A = [7, -2, 9, 54654, 7, -2, 9, 54654]; + int8 B = [14, 78, 111, -256, 14, 78, 111, -256]; + int8 R = (~A) & B; + int[8] correct = [8, 0, 102, -54784, 8, 0, 102, -54784]; + //printf("%d %d %d %d %d %d %d %d\n", R[0], R[1], R[2], R[3], R[4], R[5], R[6], R[7]); + assert(R.array == correct); +} + +} +else +{ +void test24283() { } +} + +/*****************************************/ + int main() { test21474(); @@ -300,6 +326,7 @@ int main() testunscmp(); testflt(); testdbl(); + test24283(); return 0; } From c730ebdb7d2ce1c11fddfb1e21e0e31e0ba985ad Mon Sep 17 00:00:00 2001 From: Walter Bright Date: Tue, 19 Dec 2023 17:40:04 -0800 Subject: [PATCH 133/215] ClassKindToChars() because too many toChars() --- dmd/aggregate.d | 2 +- dmd/dsymbolsem.d | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/dmd/aggregate.d b/dmd/aggregate.d index 352ca88f470..d2d44d2a152 100644 --- a/dmd/aggregate.d +++ b/dmd/aggregate.d @@ -65,7 +65,7 @@ enum ClassKind : ubyte * Returns: * 0-terminated string for `c` */ -const(char)* toChars(ClassKind c) @safe +const(char)* ClassKindToChars(ClassKind c) @safe { final switch (c) { diff --git a/dmd/dsymbolsem.d b/dmd/dsymbolsem.d index df0a9a536f4..cbfa88be3c2 100644 --- a/dmd/dsymbolsem.d +++ b/dmd/dsymbolsem.d @@ -5357,7 +5357,7 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor cldec.classKind = ClassKind.cpp; if (cldec.classKind != cldec.baseClass.classKind) .error(cldec.loc, "%s `%s` with %s linkage cannot inherit from class `%s` with %s linkage", cldec.kind, cldec.toPrettyChars, - cldec.classKind.toChars(), cldec.baseClass.toChars(), cldec.baseClass.classKind.toChars()); + ClassKindToChars(cldec.classKind), cldec.baseClass.toChars(), ClassKindToChars(cldec.baseClass.classKind)); if (cldec.baseClass.stack) cldec.stack = true; From 1521a9ef7ae44d061a6287ab6eeb73f59f876be9 Mon Sep 17 00:00:00 2001 From: Walter Bright Date: Tue, 19 Dec 2023 20:45:45 -0800 Subject: [PATCH 134/215] eliminate dependence on global.params.dihdr.fullOutput --- dmd/frontend.h | 7 +++++-- dmd/hdrgen.d | 15 +++++++++------ dmd/hdrgen.h | 2 +- dmd/main.d | 2 +- 4 files changed, 16 insertions(+), 10 deletions(-) diff --git a/dmd/frontend.h b/dmd/frontend.h index ea33176c0ad..3d8d2ef0e87 100644 --- a/dmd/frontend.h +++ b/dmd/frontend.h @@ -4051,6 +4051,7 @@ struct HdrGenState final bool ddoc; bool fullDump; bool importcHdr; + bool doFuncBodies; bool fullQual; int32_t tpltMember; int32_t autoMember; @@ -4064,6 +4065,7 @@ struct HdrGenState final ddoc(), fullDump(), importcHdr(), + doFuncBodies(), fullQual(), tpltMember(), autoMember(), @@ -4074,11 +4076,12 @@ struct HdrGenState final inEnumDecl() { } - HdrGenState(bool hdrgen, bool ddoc = false, bool fullDump = false, bool importcHdr = false, bool fullQual = false, int32_t tpltMember = 0, int32_t autoMember = 0, int32_t forStmtInit = 0, int32_t insideFuncBody = 0, int32_t insideAggregate = 0, bool declstring = false, EnumDeclaration* inEnumDecl = nullptr) : + HdrGenState(bool hdrgen, bool ddoc = false, bool fullDump = false, bool importcHdr = false, bool doFuncBodies = false, bool fullQual = false, int32_t tpltMember = 0, int32_t autoMember = 0, int32_t forStmtInit = 0, int32_t insideFuncBody = 0, int32_t insideAggregate = 0, bool declstring = false, EnumDeclaration* inEnumDecl = nullptr) : hdrgen(hdrgen), ddoc(ddoc), fullDump(fullDump), importcHdr(importcHdr), + doFuncBodies(doFuncBodies), fullQual(fullQual), tpltMember(tpltMember), autoMember(autoMember), @@ -4092,7 +4095,7 @@ struct HdrGenState final enum : int32_t { TEST_EMIT_ALL = 0 }; -extern void genhdrfile(Module* m, OutBuffer& buf); +extern void genhdrfile(Module* m, bool doFuncBodies, OutBuffer& buf); extern void moduleToBuffer(OutBuffer& buf, Module* m); diff --git a/dmd/hdrgen.d b/dmd/hdrgen.d index 0944ade4c28..e9fc58f7d24 100644 --- a/dmd/hdrgen.d +++ b/dmd/hdrgen.d @@ -60,6 +60,7 @@ struct HdrGenState bool ddoc; /// true if generating Ddoc file bool fullDump; /// true if generating a full AST dump file bool importcHdr; /// true if generating a .di file from an ImportC file + bool doFuncBodies; /// include function bodies in output bool fullQual; /// fully qualify types when printing int tpltMember; @@ -78,9 +79,10 @@ enum TEST_EMIT_ALL = 0; * Generate a header (.di) file for Module m. * Params: * m = Module to generate header for + * doFuncBodies = generate function definitions rather than just declarations * buf = buffer to write the data to */ -extern (C++) void genhdrfile(Module m, ref OutBuffer buf) +extern (C++) void genhdrfile(Module m, bool doFuncBodies, ref OutBuffer buf) { buf.doindent = 1; buf.printf("// D import file generated from '%s'", m.srcfile.toChars()); @@ -88,6 +90,7 @@ extern (C++) void genhdrfile(Module m, ref OutBuffer buf) HdrGenState hgs; hgs.hdrgen = true; hgs.importcHdr = (m.filetype == FileType.c); + hgs.doFuncBodies = doFuncBodies; toCBuffer(m, buf, hgs); } @@ -1093,12 +1096,12 @@ void toCBuffer(Dsymbol s, ref OutBuffer buf, ref HdrGenState hgs) // https://issues.dlang.org/show_bug.cgi?id=14690 // Unconditionally perform a full output dump // for `pragma(inline)` declarations. - bool savedFullDump = global.params.dihdr.fullOutput; + const saved = hgs.doFuncBodies; if (d.ident == Id.Pinline) - global.params.dihdr.fullOutput = true; + hgs.doFuncBodies = true; visitAttribDeclaration(d); - global.params.dihdr.fullOutput = savedFullDump; + hgs.doFuncBodies = saved; } void visitConditionalDeclaration(ConditionalDeclaration d) @@ -1288,7 +1291,7 @@ void toCBuffer(Dsymbol s, ref OutBuffer buf, ref HdrGenState hgs) void bodyToBuffer(FuncDeclaration f) { - if (!f.fbody || (hgs.hdrgen && global.params.dihdr.fullOutput == false && !hgs.autoMember && !hgs.tpltMember && !hgs.insideFuncBody)) + if (!f.fbody || (hgs.hdrgen && hgs.doFuncBodies == false && !hgs.autoMember && !hgs.tpltMember && !hgs.insideFuncBody)) { if (!f.fbody && (f.fensures || f.frequires)) { @@ -1706,7 +1709,7 @@ void toCBuffer(Dsymbol s, ref OutBuffer buf, ref HdrGenState hgs) bodyToBuffer(f); hgs.autoMember--; } - else if (hgs.tpltMember == 0 && global.params.dihdr.fullOutput == false && !hgs.insideFuncBody) + else if (hgs.tpltMember == 0 && hgs.doFuncBodies == false && !hgs.insideFuncBody) { if (!f.fbody) { diff --git a/dmd/hdrgen.h b/dmd/hdrgen.h index e43a35510c2..2625735e7b1 100644 --- a/dmd/hdrgen.h +++ b/dmd/hdrgen.h @@ -15,7 +15,7 @@ class Module; -void genhdrfile(Module *m, OutBuffer &buf); +void genhdrfile(Module *m, bool doFuncBodies, OutBuffer &buf); void genCppHdrFiles(Modules &ms); void moduleToBuffer(OutBuffer& buf, Module *m); const char *parametersTypeToChars(ParameterList pl); diff --git a/dmd/main.d b/dmd/main.d index ea85bc3a7a6..6ebd2a77d24 100644 --- a/dmd/main.d +++ b/dmd/main.d @@ -448,7 +448,7 @@ private int tryMain(size_t argc, const(char)** argv, ref Param params) message("import %s", m.toChars()); buf.reset(); // reuse the buffer - genhdrfile(m, buf); + genhdrfile(m, params.dihdr.fullOutput, buf); if (!writeFile(m.loc, m.hdrfile.toString(), buf[])) fatal(); } From caa590114427c5ad5b45e3d28735932b5a7703f3 Mon Sep 17 00:00:00 2001 From: Walter Bright Date: Tue, 19 Dec 2023 23:37:11 -0800 Subject: [PATCH 135/215] make toChars(Type) work (dlang/dmd!15926) --- dmd/frontend.h | 2 ++ dmd/hdrgen.d | 11 +++++++++++ dmd/mtype.d | 8 +------- dmd/mtype.h | 1 + 4 files changed, 15 insertions(+), 7 deletions(-) diff --git a/dmd/frontend.h b/dmd/frontend.h index 3d8d2ef0e87..b520652cf78 100644 --- a/dmd/frontend.h +++ b/dmd/frontend.h @@ -7999,6 +7999,8 @@ extern Expression* modifiableLvalue(Expression* _this, Scope* sc); extern const char* toChars(const Initializer* const i); +extern const char* toChars(const Type* const t); + extern void json_generate(Array& modules, OutBuffer& buf); extern JsonFieldFlags tryParseJsonField(const char* fieldName); diff --git a/dmd/hdrgen.d b/dmd/hdrgen.d index e9fc58f7d24..b17dc3df361 100644 --- a/dmd/hdrgen.d +++ b/dmd/hdrgen.d @@ -119,6 +119,17 @@ public extern (C++) const(char)* toChars(const Initializer i) return buf.extractChars(); } +public extern (C++) const(char)* toChars(const Type t) +{ + OutBuffer buf; + buf.reserve(16); + HdrGenState hgs; + hgs.fullQual = (t.ty == Tclass && !t.mod); + + toCBuffer(t, buf, null, hgs); + return buf.extractChars(); +} + public const(char)[] toString(const Initializer i) { OutBuffer buf; diff --git a/dmd/mtype.d b/dmd/mtype.d index 626bf7431f0..b9d9e0d87bc 100644 --- a/dmd/mtype.d +++ b/dmd/mtype.d @@ -525,13 +525,7 @@ extern (C++) abstract class Type : ASTNode */ final override const(char)* toChars() const { - OutBuffer buf; - buf.reserve(16); - HdrGenState hgs; - hgs.fullQual = (ty == Tclass && !mod); - - toCBuffer(this, buf, null, hgs); - return buf.extractChars(); + return dmd.hdrgen.toChars(this); } /// ditto diff --git a/dmd/mtype.h b/dmd/mtype.h index ef1ce100640..c6eacc29878 100644 --- a/dmd/mtype.h +++ b/dmd/mtype.h @@ -39,6 +39,7 @@ typedef union tree_node type; typedef struct TYPE type; #endif +extern const char* toChars(const Type* const t); Type *typeSemantic(Type *t, const Loc &loc, Scope *sc); Type *merge(Type *type); From ed3093cfff3a1cefbc9d8316ae6896d70be54a81 Mon Sep 17 00:00:00 2001 From: Walter Bright Date: Tue, 19 Dec 2023 23:34:51 -0800 Subject: [PATCH 136/215] hdrgen.d public functions use ref HdrGenState --- dmd/doc.d | 2 +- dmd/dsymbolsem.d | 4 ++-- dmd/hdrgen.d | 16 ++++++++-------- 3 files changed, 11 insertions(+), 11 deletions(-) diff --git a/dmd/doc.d b/dmd/doc.d index 03848c0274b..a154181aa3a 100644 --- a/dmd/doc.d +++ b/dmd/doc.d @@ -1296,7 +1296,7 @@ void toDocBuffer(Dsymbol s, ref OutBuffer buf, Scope* sc) Type origType = d.originalType ? d.originalType : d.type; if (origType.ty == Tfunction) { - functionToBufferFull(cast(TypeFunction)origType, *buf, d.ident, &hgs, td); + functionToBufferFull(cast(TypeFunction)origType, *buf, d.ident, hgs, td); } else toCBuffer(origType, *buf, d.ident, hgs); diff --git a/dmd/dsymbolsem.d b/dmd/dsymbolsem.d index df0a9a536f4..9edbbbfaf6c 100644 --- a/dmd/dsymbolsem.d +++ b/dmd/dsymbolsem.d @@ -4096,7 +4096,7 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor auto fd = s.isFuncDeclaration(); functionToBufferFull(cast(TypeFunction)(funcdecl.type), buf, - new Identifier(funcdecl.toPrettyChars()), &hgs, null); + new Identifier(funcdecl.toPrettyChars()), hgs, null); const(char)* funcdeclToChars = buf.peekChars(); if (fd) @@ -4119,7 +4119,7 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor else { functionToBufferFull(cast(TypeFunction)(fd.type), buf1, - new Identifier(fd.toPrettyChars()), &hgs, null); + new Identifier(fd.toPrettyChars()), hgs, null); error(funcdecl.loc, "function `%s` does not override any function, did you mean to override `%s`?", funcdeclToChars, buf1.peekChars()); diff --git a/dmd/hdrgen.d b/dmd/hdrgen.d index b17dc3df361..42a2ce323e6 100644 --- a/dmd/hdrgen.d +++ b/dmd/hdrgen.d @@ -151,14 +151,14 @@ extern (C++) void moduleToBuffer(ref OutBuffer buf, Module m) toCBuffer(m, buf, hgs); } -void moduleToBuffer2(Module m, ref OutBuffer buf, HdrGenState* hgs) +void moduleToBuffer2(Module m, ref OutBuffer buf, ref HdrGenState hgs) { if (m.md) { if (m.userAttribDecl) { buf.writestring("@("); - argsToBuffer(m.userAttribDecl.atts, buf, hgs); + argsToBuffer(m.userAttribDecl.atts, buf, &hgs); buf.writeByte(')'); buf.writenl(); } @@ -167,7 +167,7 @@ void moduleToBuffer2(Module m, ref OutBuffer buf, HdrGenState* hgs) if (m.md.msg) { buf.writestring("deprecated("); - m.md.msg.expressionToBuffer(buf, hgs); + m.md.msg.expressionToBuffer(buf, &hgs); buf.writestring(") "); } else @@ -181,7 +181,7 @@ void moduleToBuffer2(Module m, ref OutBuffer buf, HdrGenState* hgs) foreach (s; *m.members) { - s.dsymbolToBuffer(buf, hgs); + s.dsymbolToBuffer(buf, &hgs); } } @@ -1374,7 +1374,7 @@ void toCBuffer(Dsymbol s, ref OutBuffer buf, ref HdrGenState hgs) assert(fd.type); if (stcToBuffer(buf, fd.storage_class)) buf.writeByte(' '); - functionToBufferFull(cast(TypeFunction)fd.type, buf, d.ident, &hgs, d); + functionToBufferFull(cast(TypeFunction)fd.type, buf, d.ident, hgs, d); visitTemplateConstraint(d.constraint); hgs.tpltMember++; bodyToBuffer(fd); @@ -1888,7 +1888,7 @@ void toCBuffer(Dsymbol s, ref OutBuffer buf, ref HdrGenState hgs) void visitModule(Module m) { - moduleToBuffer2(m, buf, &hgs); + moduleToBuffer2(m, buf, hgs); } extern (C++) @@ -3269,10 +3269,10 @@ extern (D) string visibilityToString(Visibility.Kind kind) nothrow pure @safe } // Print the full function signature with correct ident, attributes and template args -void functionToBufferFull(TypeFunction tf, ref OutBuffer buf, const Identifier ident, HdrGenState* hgs, TemplateDeclaration td) +void functionToBufferFull(TypeFunction tf, ref OutBuffer buf, const Identifier ident, ref HdrGenState hgs, TemplateDeclaration td) { //printf("TypeFunction::toCBuffer() this = %p\n", this); - visitFuncIdentWithPrefix(tf, ident, td, buf, hgs); + visitFuncIdentWithPrefix(tf, ident, td, buf, &hgs); } // ident is inserted before the argument list and will be "function" or "delegate" for a type From bd47e9c14f9a84b4a0d0e74c7a46fe26700212b4 Mon Sep 17 00:00:00 2001 From: Walter Bright Date: Tue, 19 Dec 2023 23:07:22 -0800 Subject: [PATCH 137/215] eliminate dependence on global.params.dihdr.vcg_ast --- dmd/frontend.h | 7 +++++-- dmd/hdrgen.d | 7 +++++-- dmd/hdrgen.h | 2 +- dmd/main.d | 2 +- 4 files changed, 12 insertions(+), 6 deletions(-) diff --git a/dmd/frontend.h b/dmd/frontend.h index b520652cf78..9e25a3d356d 100644 --- a/dmd/frontend.h +++ b/dmd/frontend.h @@ -4052,6 +4052,7 @@ struct HdrGenState final bool fullDump; bool importcHdr; bool doFuncBodies; + bool vcg_ast; bool fullQual; int32_t tpltMember; int32_t autoMember; @@ -4066,6 +4067,7 @@ struct HdrGenState final fullDump(), importcHdr(), doFuncBodies(), + vcg_ast(), fullQual(), tpltMember(), autoMember(), @@ -4076,12 +4078,13 @@ struct HdrGenState final inEnumDecl() { } - HdrGenState(bool hdrgen, bool ddoc = false, bool fullDump = false, bool importcHdr = false, bool doFuncBodies = false, bool fullQual = false, int32_t tpltMember = 0, int32_t autoMember = 0, int32_t forStmtInit = 0, int32_t insideFuncBody = 0, int32_t insideAggregate = 0, bool declstring = false, EnumDeclaration* inEnumDecl = nullptr) : + HdrGenState(bool hdrgen, bool ddoc = false, bool fullDump = false, bool importcHdr = false, bool doFuncBodies = false, bool vcg_ast = false, bool fullQual = false, int32_t tpltMember = 0, int32_t autoMember = 0, int32_t forStmtInit = 0, int32_t insideFuncBody = 0, int32_t insideAggregate = 0, bool declstring = false, EnumDeclaration* inEnumDecl = nullptr) : hdrgen(hdrgen), ddoc(ddoc), fullDump(fullDump), importcHdr(importcHdr), doFuncBodies(doFuncBodies), + vcg_ast(vcg_ast), fullQual(fullQual), tpltMember(tpltMember), autoMember(autoMember), @@ -4097,7 +4100,7 @@ enum : int32_t { TEST_EMIT_ALL = 0 }; extern void genhdrfile(Module* m, bool doFuncBodies, OutBuffer& buf); -extern void moduleToBuffer(OutBuffer& buf, Module* m); +extern void moduleToBuffer(OutBuffer& buf, bool vcg_ast, Module* m); extern const char* parametersTypeToChars(ParameterList pl); diff --git a/dmd/hdrgen.d b/dmd/hdrgen.d index 42a2ce323e6..92a440a9679 100644 --- a/dmd/hdrgen.d +++ b/dmd/hdrgen.d @@ -61,6 +61,7 @@ struct HdrGenState bool fullDump; /// true if generating a full AST dump file bool importcHdr; /// true if generating a .di file from an ImportC file bool doFuncBodies; /// include function bodies in output + bool vcg_ast; /// write out codegen-ast bool fullQual; /// fully qualify types when printing int tpltMember; @@ -142,12 +143,14 @@ public const(char)[] toString(const Initializer i) * Dumps the full contents of module `m` to `buf`. * Params: * buf = buffer to write to. + * vcg_ast = write out codegen ast * m = module to visit all members of. */ -extern (C++) void moduleToBuffer(ref OutBuffer buf, Module m) +extern (C++) void moduleToBuffer(ref OutBuffer buf, bool vcg_ast, Module m) { HdrGenState hgs; hgs.fullDump = true; + hgs.vcg_ast = vcg_ast; toCBuffer(m, buf, hgs); } @@ -2486,7 +2489,7 @@ private void expressionPrettyPrint(Expression e, ref OutBuffer buf, HdrGenState* void visitLoweredAssignExp(LoweredAssignExp e) { - if (global.params.vcg_ast) + if (hgs.vcg_ast) { expressionToBuffer(e.lowering, buf, hgs); return; diff --git a/dmd/hdrgen.h b/dmd/hdrgen.h index 2625735e7b1..fb5fbadae36 100644 --- a/dmd/hdrgen.h +++ b/dmd/hdrgen.h @@ -17,5 +17,5 @@ class Module; void genhdrfile(Module *m, bool doFuncBodies, OutBuffer &buf); void genCppHdrFiles(Modules &ms); -void moduleToBuffer(OutBuffer& buf, Module *m); +void moduleToBuffer(OutBuffer& buf, bool vcg_ast, Module *m); const char *parametersTypeToChars(ParameterList pl); diff --git a/dmd/main.d b/dmd/main.d index 6ebd2a77d24..27f86bdb4a9 100644 --- a/dmd/main.d +++ b/dmd/main.d @@ -589,7 +589,7 @@ private int tryMain(size_t argc, const(char)** argv, ref Param params) { auto buf = OutBuffer(); buf.doindent = 1; - moduleToBuffer(buf, mod); + moduleToBuffer(buf, params.vcg_ast, mod); // write the output to $(filename).cg auto cgFilename = FileName.addExt(mod.srcfile.toString(), "cg"); From b2c1b49f12d025438c2ce54984bc787e278af95b Mon Sep 17 00:00:00 2001 From: Walter Bright Date: Wed, 20 Dec 2023 02:19:30 -0800 Subject: [PATCH 138/215] PtrStateToChars() because too many toChars() (dlang/dmd!15929) --- dmd/ob.d | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dmd/ob.d b/dmd/ob.d index dc94aecc61b..51a141089d2 100644 --- a/dmd/ob.d +++ b/dmd/ob.d @@ -197,7 +197,7 @@ enum PtrState : ubyte /************ */ -const(char)* toChars(PtrState state) +const(char)* PtrStateToChars(PtrState state) { return toString(state).ptr; } @@ -2490,7 +2490,7 @@ void checkObErrors(ref ObState obstate) if (s1 != s2 && (s1 == PtrState.Owner || s2 == PtrState.Owner)) { auto v = obstate.vars[i]; - .error(ob.exp ? ob.exp.loc : v.loc, "%s `%s` is both %s and %s", v.kind, v.toPrettyChars, s1.toChars(), s2.toChars()); + .error(ob.exp ? ob.exp.loc : v.loc, "%s `%s` is both %s and %s", v.kind, v.toPrettyChars, PtrStateToChars(s1), PtrStateToChars(s2)); } pvs1.combine(*pvs2, i, ob.gen); } From 3b101e31e00b3fe1e34d27710ac50b76759c7113 Mon Sep 17 00:00:00 2001 From: Walter Bright Date: Wed, 20 Dec 2023 02:21:16 -0800 Subject: [PATCH 139/215] ScopeRefToChars() because too many toChars() (dlang/dmd!15927) --- dmd/escape.d | 2 +- dmd/mtype.d | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/dmd/escape.d b/dmd/escape.d index f928b08503a..be171158275 100644 --- a/dmd/escape.d +++ b/dmd/escape.d @@ -1296,7 +1296,7 @@ private bool checkReturnEscapeImpl(Scope* sc, Expression e, bool refs, bool gag) { if (log) { - printf("byref `%s` %s\n", v.toChars(), toChars(buildScopeRef(v.storage_class))); + printf("byref `%s` %s\n", v.toChars(), ScopeRefToChars(buildScopeRef(v.storage_class))); } // 'featureState' tells us whether to emit an error or a deprecation, diff --git a/dmd/mtype.d b/dmd/mtype.d index b9d9e0d87bc..60ede9d6aa6 100644 --- a/dmd/mtype.d +++ b/dmd/mtype.d @@ -6733,7 +6733,7 @@ enum ScopeRef * Returns: * corresponding string */ -const(char)* toChars(ScopeRef sr) pure nothrow @nogc @safe +const(char)* ScopeRefToChars(ScopeRef sr) pure nothrow @nogc @safe { with (ScopeRef) { From 73496f36aef303c57928bf655f0e78e0c513940e Mon Sep 17 00:00:00 2001 From: Razvan Nitu Date: Wed, 20 Dec 2023 15:12:10 +0200 Subject: [PATCH 140/215] Update C++ header for StructLiteralExp (dlang/dmd!15933) --- dmd/expression.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dmd/expression.h b/dmd/expression.h index 464094c4126..f757c15c28e 100644 --- a/dmd/expression.h +++ b/dmd/expression.h @@ -434,7 +434,7 @@ class StructLiteralExp final : public Expression union { - void *sym; // back end symbol to initialize with literal (used as a Symbol*) + Symbol *sym; // back end symbol to initialize with literal (used as a Symbol*) // those fields need to prevent a infinite recursion when one field of struct initialized with 'this' pointer. StructLiteralExp *inlinecopy; From f248f427250b6b365ff8e4ecb3c9cf4ccd128536 Mon Sep 17 00:00:00 2001 From: Walter Bright Date: Wed, 20 Dec 2023 23:02:47 -0800 Subject: [PATCH 141/215] oneMember() should use out for ps --- dmd/attrib.d | 18 +++++++++--------- dmd/attrib.h | 8 ++++---- dmd/denum.d | 2 +- dmd/dsymbol.d | 30 +++++++++++++++--------------- dmd/dsymbol.h | 2 +- dmd/dsymbolsem.d | 6 +++--- dmd/dtemplate.d | 10 +++++----- dmd/enum.h | 2 +- dmd/frontend.h | 18 +++++++++--------- dmd/staticassert.d | 4 ++-- dmd/staticassert.h | 2 +- dmd/template.h | 4 ++-- 12 files changed, 53 insertions(+), 53 deletions(-) diff --git a/dmd/attrib.d b/dmd/attrib.d index cc6ef9c431b..c37ac01e711 100644 --- a/dmd/attrib.d +++ b/dmd/attrib.d @@ -137,7 +137,7 @@ extern (C++) abstract class AttribDeclaration : Dsymbol return "attribute"; } - override bool oneMember(Dsymbol* ps, Identifier ident) + override bool oneMember(out Dsymbol ps, Identifier ident) { Dsymbols* d = include(null); return Dsymbol.oneMembers(d, ps, ident); @@ -225,10 +225,10 @@ extern (C++) class StorageClassDeclaration : AttribDeclaration sc.visibility, sc.explicitVisibility, sc.aligndecl, sc.inlining); } - override final bool oneMember(Dsymbol* ps, Identifier ident) + override final bool oneMember(out Dsymbol ps, Identifier ident) { bool t = Dsymbol.oneMembers(decl, ps, ident); - if (t && *ps) + if (t && ps) { /* This is to deal with the following case: * struct Tick { @@ -238,7 +238,7 @@ extern (C++) class StorageClassDeclaration : AttribDeclaration * before the semantic analysis of 'to', so that template overloading based on the * 'this' pointer can be successful. */ - FuncDeclaration fd = (*ps).isFuncDeclaration(); + FuncDeclaration fd = ps.isFuncDeclaration(); if (fd) { /* Use storage_class2 instead of storage_class otherwise when we do .di generation @@ -743,7 +743,7 @@ extern (C++) class ConditionalDeclaration : AttribDeclaration return new ConditionalDeclaration(loc, condition.syntaxCopy(), Dsymbol.arraySyntaxCopy(decl), Dsymbol.arraySyntaxCopy(elsedecl)); } - override final bool oneMember(Dsymbol* ps, Identifier ident) + override final bool oneMember(out Dsymbol ps, Identifier ident) { //printf("ConditionalDeclaration::oneMember(), inc = %d\n", condition.inc); if (condition.inc != Include.notComputed) @@ -753,8 +753,8 @@ extern (C++) class ConditionalDeclaration : AttribDeclaration } else { - bool res = (Dsymbol.oneMembers(decl, ps, ident) && *ps is null && Dsymbol.oneMembers(elsedecl, ps, ident) && *ps is null); - *ps = null; + bool res = (Dsymbol.oneMembers(decl, ps, ident) && ps is null && Dsymbol.oneMembers(elsedecl, ps, ident) && ps is null); + ps = null; return res; } } @@ -901,7 +901,7 @@ extern (C++) final class StaticForeachDeclaration : AttribDeclaration Dsymbol.arraySyntaxCopy(decl)); } - override bool oneMember(Dsymbol* ps, Identifier ident) + override bool oneMember(out Dsymbol ps, Identifier ident) { // Required to support IFTI on a template that contains a // `static foreach` declaration. `super.oneMember` calls @@ -912,7 +912,7 @@ extern (C++) final class StaticForeachDeclaration : AttribDeclaration { return super.oneMember(ps, ident); } - *ps = null; // a `static foreach` declaration may in general expand to multiple symbols + ps = null; // a `static foreach` declaration may in general expand to multiple symbols return false; } diff --git a/dmd/attrib.h b/dmd/attrib.h index 35628e26105..9b2340b9269 100644 --- a/dmd/attrib.h +++ b/dmd/attrib.h @@ -28,7 +28,7 @@ class AttribDeclaration : public Dsymbol virtual Scope *newScope(Scope *sc); void addComment(const utf8_t *comment) override; const char *kind() const override; - bool oneMember(Dsymbol **ps, Identifier *ident) override; + bool oneMember(Dsymbol *&ps, Identifier *ident) override; bool hasPointers() override final; bool hasStaticCtorOrDtor() override final; void checkCtorConstInit() override final; @@ -44,7 +44,7 @@ class StorageClassDeclaration : public AttribDeclaration StorageClassDeclaration *syntaxCopy(Dsymbol *s) override; Scope *newScope(Scope *sc) override; - bool oneMember(Dsymbol **ps, Identifier *ident) override final; + bool oneMember(Dsymbol *&ps, Identifier *ident) override final; StorageClassDeclaration *isStorageClassDeclaration() override { return this; } void accept(Visitor *v) override { v->visit(this); } @@ -153,7 +153,7 @@ class ConditionalDeclaration : public AttribDeclaration Dsymbols *elsedecl; // array of Dsymbol's for else block ConditionalDeclaration *syntaxCopy(Dsymbol *s) override; - bool oneMember(Dsymbol **ps, Identifier *ident) override final; + bool oneMember(Dsymbol *&ps, Identifier *ident) override final; Dsymbols *include(Scope *sc) override; void addComment(const utf8_t *comment) override final; void accept(Visitor *v) override { v->visit(this); } @@ -183,7 +183,7 @@ class StaticForeachDeclaration final : public AttribDeclaration Dsymbols *cache; StaticForeachDeclaration *syntaxCopy(Dsymbol *s) override; - bool oneMember(Dsymbol **ps, Identifier *ident) override; + bool oneMember(Dsymbol *&ps, Identifier *ident) override; Dsymbols *include(Scope *sc) override; void addComment(const utf8_t *comment) override; const char *kind() const override; diff --git a/dmd/denum.d b/dmd/denum.d index 5713be1e99e..e7a237ce0f9 100644 --- a/dmd/denum.d +++ b/dmd/denum.d @@ -83,7 +83,7 @@ extern (C++) final class EnumDeclaration : ScopeDsymbol return ed; } - override bool oneMember(Dsymbol* ps, Identifier ident) + override bool oneMember(out Dsymbol ps, Identifier ident) { if (isAnonymous()) return Dsymbol.oneMembers(members, ps, ident); diff --git a/dmd/dsymbol.d b/dmd/dsymbol.d index 6613c2bc5c2..b4e3f433348 100644 --- a/dmd/dsymbol.d +++ b/dmd/dsymbol.d @@ -845,27 +845,27 @@ extern (C++) class Dsymbol : ASTNode /************************************** * Determine if this symbol is only one. * Returns: - * false, *ps = NULL: There are 2 or more symbols - * true, *ps = NULL: There are zero symbols - * true, *ps = symbol: The one and only one symbol + * false, ps = null: There are 2 or more symbols + * true, ps = null: There are zero symbols + * true, ps = symbol: The one and only one symbol */ - bool oneMember(Dsymbol* ps, Identifier ident) + bool oneMember(out Dsymbol ps, Identifier ident) { //printf("Dsymbol::oneMember()\n"); - *ps = this; + ps = this; return true; } /***************************************** * Same as Dsymbol::oneMember(), but look at an array of Dsymbols. */ - extern (D) static bool oneMembers(Dsymbols* members, Dsymbol* ps, Identifier ident) + extern (D) static bool oneMembers(Dsymbols* members, out Dsymbol ps, Identifier ident) { //printf("Dsymbol::oneMembers() %d\n", members ? members.length : 0); Dsymbol s = null; if (!members) { - *ps = null; + ps = null; return true; } @@ -877,21 +877,21 @@ extern (C++) class Dsymbol : ASTNode if (!x) { //printf("\tfalse 1\n"); - assert(*ps is null); + assert(ps is null); return false; } - if (*ps) + if (ps) { assert(ident); - if (!(*ps).ident || !(*ps).ident.equals(ident)) + if (!ps.ident || !ps.ident.equals(ident)) continue; if (!s) - s = *ps; - else if (s.isOverloadable() && (*ps).isOverloadable()) + s = ps; + else if (s.isOverloadable() && ps.isOverloadable()) { // keep head of overload set FuncDeclaration f1 = s.isFuncDeclaration(); - FuncDeclaration f2 = (*ps).isFuncDeclaration(); + FuncDeclaration f2 = ps.isFuncDeclaration(); if (f1 && f2) { assert(!f1.isFuncAliasDeclaration()); @@ -908,13 +908,13 @@ extern (C++) class Dsymbol : ASTNode } else // more than one symbol { - *ps = null; + ps = null; //printf("\tfalse 2\n"); return false; } } } - *ps = s; // s is the one symbol, null if none + ps = s; // s is the one symbol, null if none //printf("\ttrue\n"); return true; } diff --git a/dmd/dsymbol.h b/dmd/dsymbol.h index d029c00fc1c..0137edcf45c 100644 --- a/dmd/dsymbol.h +++ b/dmd/dsymbol.h @@ -246,7 +246,7 @@ class Dsymbol : public ASTNode virtual bool needThis(); // need a 'this' pointer? virtual Visibility visible(); virtual Dsymbol *syntaxCopy(Dsymbol *s); // copy only syntax trees - virtual bool oneMember(Dsymbol **ps, Identifier *ident); + virtual bool oneMember(Dsymbol *&ps, Identifier *ident); virtual bool hasPointers(); virtual bool hasStaticCtorOrDtor(); virtual void addObjcSymbols(ClassDeclarations *, ClassDeclarations *) { } diff --git a/dmd/dsymbolsem.d b/dmd/dsymbolsem.d index 02be04f8f98..1d5d11a3c09 100644 --- a/dmd/dsymbolsem.d +++ b/dmd/dsymbolsem.d @@ -2964,7 +2964,7 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor if (tempdecl.members) { Dsymbol s; - if (Dsymbol.oneMembers(tempdecl.members, &s, tempdecl.ident) && s) + if (Dsymbol.oneMembers(tempdecl.members, s, tempdecl.ident) && s) { tempdecl.onemember = s; s.parent = tempdecl; @@ -6807,7 +6807,7 @@ void templateInstanceSemantic(TemplateInstance tempinst, Scope* sc, ArgumentList if (tempinst.members.length) { Dsymbol s; - if (Dsymbol.oneMembers(tempinst.members, &s, tempdecl.ident) && s) + if (Dsymbol.oneMembers(tempinst.members, s, tempdecl.ident) && s) { //printf("tempdecl.ident = %s, s = `%s %s`\n", tempdecl.ident.toChars(), s.kind(), s.toPrettyChars()); //printf("setting aliasdecl\n"); @@ -6852,7 +6852,7 @@ void templateInstanceSemantic(TemplateInstance tempinst, Scope* sc, ArgumentList if (tempinst.members.length) { Dsymbol s; - if (Dsymbol.oneMembers(tempinst.members, &s, tempdecl.ident) && s) + if (Dsymbol.oneMembers(tempinst.members, s, tempdecl.ident) && s) { if (!tempinst.aliasdecl || tempinst.aliasdecl != s) { diff --git a/dmd/dtemplate.d b/dmd/dtemplate.d index e440b9e2eb6..82f0e57078a 100644 --- a/dmd/dtemplate.d +++ b/dmd/dtemplate.d @@ -615,7 +615,7 @@ extern (C++) final class TemplateDeclaration : ScopeDsymbol return; Dsymbol s; - if (!Dsymbol.oneMembers(members, &s, ident) || !s) + if (!Dsymbol.oneMembers(members, s, ident) || !s) return; onemember = s; @@ -6029,9 +6029,9 @@ extern (C++) class TemplateInstance : ScopeDsymbol return "template instance"; } - override bool oneMember(Dsymbol* ps, Identifier ident) + override bool oneMember(out Dsymbol ps, Identifier ident) { - *ps = null; + ps = null; return true; } @@ -7599,7 +7599,7 @@ extern (C++) class TemplateInstance : ScopeDsymbol if (members.length) { Dsymbol sa; - if (Dsymbol.oneMembers(members, &sa, tempdecl.ident) && sa) + if (Dsymbol.oneMembers(members, sa, tempdecl.ident) && sa) aliasdecl = sa; } done = true; @@ -7820,7 +7820,7 @@ extern (C++) final class TemplateMixin : TemplateInstance return "mixin"; } - override bool oneMember(Dsymbol* ps, Identifier ident) + override bool oneMember(out Dsymbol ps, Identifier ident) { return Dsymbol.oneMember(ps, ident); } diff --git a/dmd/enum.h b/dmd/enum.h index 5f91ead9e17..740b6cb7e6c 100644 --- a/dmd/enum.h +++ b/dmd/enum.h @@ -46,7 +46,7 @@ class EnumDeclaration final : public ScopeDsymbol bool inuse(bool v); EnumDeclaration *syntaxCopy(Dsymbol *s) override; - bool oneMember(Dsymbol **ps, Identifier *ident) override; + bool oneMember(Dsymbol *&ps, Identifier *ident) override; Type *getType() override; const char *kind() const override; bool isDeprecated() const override; // is Dsymbol deprecated? diff --git a/dmd/frontend.h b/dmd/frontend.h index 9e25a3d356d..7e970735d5e 100644 --- a/dmd/frontend.h +++ b/dmd/frontend.h @@ -513,7 +513,7 @@ class Dsymbol : public ASTNode virtual bool needThis(); virtual Visibility visible(); virtual Dsymbol* syntaxCopy(Dsymbol* s); - virtual bool oneMember(Dsymbol** ps, Identifier* ident); + virtual bool oneMember(Dsymbol*& ps, Identifier* ident); virtual bool hasPointers(); virtual bool hasStaticCtorOrDtor(); virtual void addObjcSymbols(Array* classes, Array* categories); @@ -1505,7 +1505,7 @@ class TemplateInstance : public ScopeDsymbol TemplateInstance* syntaxCopy(Dsymbol* s) override; Dsymbol* toAlias() final override; const char* kind() const override; - bool oneMember(Dsymbol** ps, Identifier* ident) override; + bool oneMember(Dsymbol*& ps, Identifier* ident) override; const char* toChars() const override; const char* toPrettyCharsHelper() final override; Identifier* getIdent() final override; @@ -1531,7 +1531,7 @@ class TemplateMixin final : public TemplateInstance TypeQualified* tqual; TemplateInstance* syntaxCopy(Dsymbol* s) override; const char* kind() const override; - bool oneMember(Dsymbol** ps, Identifier* ident) override; + bool oneMember(Dsymbol*& ps, Identifier* ident) override; bool hasPointers() override; const char* toChars() const override; TemplateMixin* isTemplateMixin() override; @@ -5965,7 +5965,7 @@ class StaticAssert final : public Dsymbol Expression* exp; Array* msgs; StaticAssert* syntaxCopy(Dsymbol* s) override; - bool oneMember(Dsymbol** ps, Identifier* ident) override; + bool oneMember(Dsymbol*& ps, Identifier* ident) override; const char* kind() const override; StaticAssert* isStaticAssert() override; void accept(Visitor* v) override; @@ -6795,7 +6795,7 @@ class AttribDeclaration : public Dsymbol virtual Scope* newScope(Scope* sc); void addComment(const char* comment) override; const char* kind() const override; - bool oneMember(Dsymbol** ps, Identifier* ident) override; + bool oneMember(Dsymbol*& ps, Identifier* ident) override; bool hasPointers() final override; bool hasStaticCtorOrDtor() final override; void checkCtorConstInit() final override; @@ -6810,7 +6810,7 @@ class StorageClassDeclaration : public AttribDeclaration StorageClass stc; StorageClassDeclaration* syntaxCopy(Dsymbol* s) override; Scope* newScope(Scope* sc) override; - bool oneMember(Dsymbol** ps, Identifier* ident) final override; + bool oneMember(Dsymbol*& ps, Identifier* ident) final override; StorageClassDeclaration* isStorageClassDeclaration() override; void accept(Visitor* v) override; }; @@ -6910,7 +6910,7 @@ class ConditionalDeclaration : public AttribDeclaration Condition* condition; Array* elsedecl; ConditionalDeclaration* syntaxCopy(Dsymbol* s) override; - bool oneMember(Dsymbol** ps, Identifier* ident) final override; + bool oneMember(Dsymbol*& ps, Identifier* ident) final override; Array* include(Scope* sc) override; void addComment(const char* comment) final override; void accept(Visitor* v) override; @@ -6940,7 +6940,7 @@ class StaticForeachDeclaration final : public AttribDeclaration bool cached; Array* cache; StaticForeachDeclaration* syntaxCopy(Dsymbol* s) override; - bool oneMember(Dsymbol** ps, Identifier* ident) override; + bool oneMember(Dsymbol*& ps, Identifier* ident) override; Array* include(Scope* sc) override; void addComment(const char* comment) override; const char* kind() const override; @@ -7519,7 +7519,7 @@ class EnumDeclaration final : public ScopeDsymbol uint8_t bitFields; public: EnumDeclaration* syntaxCopy(Dsymbol* s) override; - bool oneMember(Dsymbol** ps, Identifier* ident) override; + bool oneMember(Dsymbol*& ps, Identifier* ident) override; Type* getType() override; const char* kind() const override; bool isDeprecated() const override; diff --git a/dmd/staticassert.d b/dmd/staticassert.d index 760c66a415a..7cd042e7832 100644 --- a/dmd/staticassert.d +++ b/dmd/staticassert.d @@ -49,10 +49,10 @@ extern (C++) final class StaticAssert : Dsymbol return new StaticAssert(loc, exp.syntaxCopy(), msgs ? Expression.arraySyntaxCopy(msgs) : null); } - override bool oneMember(Dsymbol* ps, Identifier ident) + override bool oneMember(out Dsymbol ps, Identifier ident) { //printf("StaticAssert::oneMember())\n"); - *ps = null; + ps = null; return true; } diff --git a/dmd/staticassert.h b/dmd/staticassert.h index c0d5363a414..f03ef61c03e 100644 --- a/dmd/staticassert.h +++ b/dmd/staticassert.h @@ -21,7 +21,7 @@ class StaticAssert : public Dsymbol Expressions *msg; StaticAssert *syntaxCopy(Dsymbol *s) override; - bool oneMember(Dsymbol **ps, Identifier *ident) override; + bool oneMember(Dsymbol *&ps, Identifier *ident) override; const char *kind() const override; StaticAssert *isStaticAssert() override { return this; } void accept(Visitor *v) override { v->visit(this); } diff --git a/dmd/template.h b/dmd/template.h index 4be136102c2..cc7578454a4 100644 --- a/dmd/template.h +++ b/dmd/template.h @@ -290,7 +290,7 @@ class TemplateInstance : public ScopeDsymbol TemplateInstance *syntaxCopy(Dsymbol *) override; Dsymbol *toAlias() override final; // resolve real symbol const char *kind() const override; - bool oneMember(Dsymbol **ps, Identifier *ident) override; + bool oneMember(Dsymbol *&ps, Identifier *ident) override; const char *toChars() const override; const char* toPrettyCharsHelper() override final; Identifier *getIdent() override final; @@ -309,7 +309,7 @@ class TemplateMixin final : public TemplateInstance TemplateMixin *syntaxCopy(Dsymbol *s) override; const char *kind() const override; - bool oneMember(Dsymbol **ps, Identifier *ident) override; + bool oneMember(Dsymbol *&ps, Identifier *ident) override; bool hasPointers() override; const char *toChars() const override; From 25f308a14b10910384857b4246bb613cd27df009 Mon Sep 17 00:00:00 2001 From: Walter Bright Date: Wed, 20 Dec 2023 22:32:45 -0800 Subject: [PATCH 142/215] many more HdrGenState * to ref --- dmd/hdrgen.d | 186 +++++++++++++++++++++++++-------------------------- 1 file changed, 93 insertions(+), 93 deletions(-) diff --git a/dmd/hdrgen.d b/dmd/hdrgen.d index 92a440a9679..5820336a068 100644 --- a/dmd/hdrgen.d +++ b/dmd/hdrgen.d @@ -161,7 +161,7 @@ void moduleToBuffer2(Module m, ref OutBuffer buf, ref HdrGenState hgs) if (m.userAttribDecl) { buf.writestring("@("); - argsToBuffer(m.userAttribDecl.atts, buf, &hgs); + argsToBuffer(m.userAttribDecl.atts, buf, hgs); buf.writeByte(')'); buf.writenl(); } @@ -170,7 +170,7 @@ void moduleToBuffer2(Module m, ref OutBuffer buf, ref HdrGenState hgs) if (m.md.msg) { buf.writestring("deprecated("); - m.md.msg.expressionToBuffer(buf, &hgs); + m.md.msg.expressionToBuffer(buf, hgs); buf.writestring(") "); } else @@ -184,11 +184,11 @@ void moduleToBuffer2(Module m, ref OutBuffer buf, ref HdrGenState hgs) foreach (s; *m.members) { - s.dsymbolToBuffer(buf, &hgs); + s.dsymbolToBuffer(buf, hgs); } } -private void statementToBuffer(Statement s, ref OutBuffer buf, HdrGenState* hgs) +private void statementToBuffer(Statement s, ref OutBuffer buf, ref HdrGenState hgs) { void visitDefaultCase(Statement s) { @@ -257,7 +257,7 @@ private void statementToBuffer(Statement s, ref OutBuffer buf, HdrGenState* hgs) auto d = ds.exp.isDeclarationExp().declaration; if (auto v = d.isVarDeclaration()) { - visitVarDecl(v, anywritten, buf, *hgs); + visitVarDecl(v, anywritten, buf, hgs); } else d.dsymbolToBuffer(buf, hgs); @@ -861,9 +861,9 @@ private void statementToBuffer(Statement s, ref OutBuffer buf, HdrGenState* hgs) visit.VisitStatement(s); } -private void dsymbolToBuffer(Dsymbol s, ref OutBuffer buf, HdrGenState* hgs) +private void dsymbolToBuffer(Dsymbol s, ref OutBuffer buf, ref HdrGenState hgs) { - toCBuffer(s, buf, *hgs); + toCBuffer(s, buf, hgs); } void toCBuffer(Dsymbol s, ref OutBuffer buf, ref HdrGenState hgs) @@ -877,13 +877,13 @@ void toCBuffer(Dsymbol s, ref OutBuffer buf, ref HdrGenState hgs) { buf.writestring(s.kind()); buf.writeByte('('); - s.exp.expressionToBuffer(buf, &hgs); + s.exp.expressionToBuffer(buf, hgs); if (s.msgs) { foreach (m; (*s.msgs)[]) { buf.writestring(", "); - m.expressionToBuffer(buf, &hgs); + m.expressionToBuffer(buf, hgs); } } buf.writestring(");"); @@ -915,13 +915,13 @@ void toCBuffer(Dsymbol s, ref OutBuffer buf, ref HdrGenState hgs) void visitEnumMember(EnumMember em) { if (em.type) - typeToBuffer(em.type, em.ident, buf, &hgs); + typeToBuffer(em.type, em.ident, buf, hgs); else buf.writestring(em.ident.toString()); if (em.value) { buf.writestring(" = "); - em.value.expressionToBuffer(buf, &hgs); + em.value.expressionToBuffer(buf, hgs); } } @@ -1014,7 +1014,7 @@ void toCBuffer(Dsymbol s, ref OutBuffer buf, ref HdrGenState hgs) void visitDeprecatedDeclaration(DeprecatedDeclaration d) { buf.writestring("deprecated("); - d.msg.expressionToBuffer(buf, &hgs); + d.msg.expressionToBuffer(buf, hgs); buf.writestring(") "); visitAttribDeclaration(d); } @@ -1102,7 +1102,7 @@ void toCBuffer(Dsymbol s, ref OutBuffer buf, ref HdrGenState hgs) if (d.args && d.args.length) { buf.writestring(", "); - argsToBuffer(d.args, buf, &hgs); + argsToBuffer(d.args, buf, hgs); } buf.writeByte(')'); @@ -1120,7 +1120,7 @@ void toCBuffer(Dsymbol s, ref OutBuffer buf, ref HdrGenState hgs) void visitConditionalDeclaration(ConditionalDeclaration d) { - d.condition.conditionToBuffer(buf, &hgs); + d.condition.conditionToBuffer(buf, hgs); if (d.decl || d.elsedecl) { buf.writenl(); @@ -1166,12 +1166,12 @@ void toCBuffer(Dsymbol s, ref OutBuffer buf, ref HdrGenState hgs) if (stcToBuffer(buf, p.storageClass)) buf.writeByte(' '); if (p.type) - typeToBuffer(p.type, p.ident, buf, &hgs); + typeToBuffer(p.type, p.ident, buf, hgs); else buf.writestring(p.ident.toString()); } buf.writestring("; "); - s.aggr.expressionToBuffer(buf, &hgs); + s.aggr.expressionToBuffer(buf, hgs); buf.writeByte(')'); buf.writenl(); } @@ -1183,13 +1183,13 @@ void toCBuffer(Dsymbol s, ref OutBuffer buf, ref HdrGenState hgs) buf.writestring(Token.toString(s.op)); buf.writestring(" ("); if (s.prm.type) - typeToBuffer(s.prm.type, s.prm.ident, buf, &hgs); + typeToBuffer(s.prm.type, s.prm.ident, buf, hgs); else buf.writestring(s.prm.ident.toString()); buf.writestring("; "); - s.lwr.expressionToBuffer(buf, &hgs); + s.lwr.expressionToBuffer(buf, hgs); buf.writestring(" .. "); - s.upr.expressionToBuffer(buf, &hgs); + s.upr.expressionToBuffer(buf, hgs); buf.writeByte(')'); buf.writenl(); } @@ -1217,7 +1217,7 @@ void toCBuffer(Dsymbol s, ref OutBuffer buf, ref HdrGenState hgs) void visitMixinDeclaration(MixinDeclaration d) { buf.writestring("mixin("); - argsToBuffer(d.exps, buf, &hgs, null); + argsToBuffer(d.exps, buf, hgs, null); buf.writestring(");"); buf.writenl(); } @@ -1225,7 +1225,7 @@ void toCBuffer(Dsymbol s, ref OutBuffer buf, ref HdrGenState hgs) void visitUserAttributeDeclaration(UserAttributeDeclaration d) { buf.writestring("@("); - argsToBuffer(d.atts, buf, &hgs); + argsToBuffer(d.atts, buf, hgs); buf.writeByte(')'); visitAttribDeclaration(d); } @@ -1235,7 +1235,7 @@ void toCBuffer(Dsymbol s, ref OutBuffer buf, ref HdrGenState hgs) if (!constraint) return; buf.writestring(" if ("); - constraint.expressionToBuffer(buf, &hgs); + constraint.expressionToBuffer(buf, hgs); buf.writeByte(')'); } @@ -1253,7 +1253,7 @@ void toCBuffer(Dsymbol s, ref OutBuffer buf, ref HdrGenState hgs) { assert(es.exp && es.exp.op == EXP.assert_); buf.writestring(" ("); - (cast(AssertExp)es.exp).e1.expressionToBuffer(buf, &hgs); + (cast(AssertExp)es.exp).e1.expressionToBuffer(buf, hgs); buf.writeByte(')'); buf.writenl(); requireDo = false; @@ -1261,7 +1261,7 @@ void toCBuffer(Dsymbol s, ref OutBuffer buf, ref HdrGenState hgs) else { buf.writenl(); - frequire.statementToBuffer(buf, &hgs); + frequire.statementToBuffer(buf, hgs); requireDo = true; } } @@ -1281,7 +1281,7 @@ void toCBuffer(Dsymbol s, ref OutBuffer buf, ref HdrGenState hgs) buf.writestring(fensure.id.toString()); } buf.writestring("; "); - (cast(AssertExp)es.exp).e1.expressionToBuffer(buf, &hgs); + (cast(AssertExp)es.exp).e1.expressionToBuffer(buf, hgs); buf.writeByte(')'); buf.writenl(); requireDo = false; @@ -1295,7 +1295,7 @@ void toCBuffer(Dsymbol s, ref OutBuffer buf, ref HdrGenState hgs) buf.writeByte(')'); } buf.writenl(); - fensure.ensure.statementToBuffer(buf, &hgs); + fensure.ensure.statementToBuffer(buf, hgs); requireDo = true; } } @@ -1343,7 +1343,7 @@ void toCBuffer(Dsymbol s, ref OutBuffer buf, ref HdrGenState hgs) buf.writeByte('{'); buf.writenl(); buf.level++; - f.fbody.statementToBuffer(buf, &hgs); + f.fbody.statementToBuffer(buf, hgs); buf.level--; buf.writeByte('}'); buf.writenl(); @@ -1361,7 +1361,7 @@ void toCBuffer(Dsymbol s, ref OutBuffer buf, ref HdrGenState hgs) { if (i) buf.writestring(", "); - typeToBuffer(b.type, null, buf, &hgs); + typeToBuffer(b.type, null, buf, hgs); } } @@ -1419,7 +1419,7 @@ void toCBuffer(Dsymbol s, ref OutBuffer buf, ref HdrGenState hgs) if (stcToBuffer(buf, vd.storage_class)) buf.writeByte(' '); if (vd.type) - typeToBuffer(vd.type, vd.ident, buf, &hgs); + typeToBuffer(vd.type, vd.ident, buf, hgs); else buf.writestring(vd.ident.toString()); buf.writeByte('('); @@ -1430,9 +1430,9 @@ void toCBuffer(Dsymbol s, ref OutBuffer buf, ref HdrGenState hgs) buf.writestring(" = "); ExpInitializer ie = vd._init.isExpInitializer(); if (ie && (ie.exp.op == EXP.construct || ie.exp.op == EXP.blit)) - (cast(AssignExp)ie.exp).e2.expressionToBuffer(buf, &hgs); + (cast(AssignExp)ie.exp).e2.expressionToBuffer(buf, hgs); else - vd._init.initializerToBuffer(buf, &hgs); + vd._init.initializerToBuffer(buf, hgs); } buf.writeByte(';'); buf.writenl(); @@ -1480,20 +1480,20 @@ void toCBuffer(Dsymbol s, ref OutBuffer buf, ref HdrGenState hgs) void visitTemplateInstance(TemplateInstance ti) { buf.writestring(ti.name.toChars()); - tiargsToBuffer(ti, buf, &hgs); + tiargsToBuffer(ti, buf, hgs); if (hgs.fullDump) { buf.writenl(); - dumpTemplateInstance(ti, buf, &hgs); + dumpTemplateInstance(ti, buf, hgs); } } void visitTemplateMixin(TemplateMixin tm) { buf.writestring("mixin "); - typeToBuffer(tm.tqual, null, buf, &hgs); - tiargsToBuffer(tm, buf, &hgs); + typeToBuffer(tm.tqual, null, buf, hgs); + tiargsToBuffer(tm, buf, hgs); if (tm.ident && memcmp(tm.ident.toChars(), cast(const(char)*)"__mixin", 7) != 0) { buf.writeByte(' '); @@ -1502,7 +1502,7 @@ void toCBuffer(Dsymbol s, ref OutBuffer buf, ref HdrGenState hgs) buf.writeByte(';'); buf.writenl(); if (hgs.fullDump) - dumpTemplateInstance(tm, buf, &hgs); + dumpTemplateInstance(tm, buf, hgs); } void visitEnumDeclaration(EnumDeclaration d) @@ -1518,7 +1518,7 @@ void toCBuffer(Dsymbol s, ref OutBuffer buf, ref HdrGenState hgs) if (d.memtype) { buf.writestring(" : "); - typeToBuffer(d.memtype, null, buf, &hgs); + typeToBuffer(d.memtype, null, buf, hgs); } if (!d.members) { @@ -1666,7 +1666,7 @@ void toCBuffer(Dsymbol s, ref OutBuffer buf, ref HdrGenState hgs) { if (stcToBuffer(buf, d.storage_class)) buf.writeByte(' '); - typeToBuffer(d.type, d.ident, buf, &hgs); + typeToBuffer(d.type, d.ident, buf, hgs); } else if (d.ident) { @@ -1675,7 +1675,7 @@ void toCBuffer(Dsymbol s, ref OutBuffer buf, ref HdrGenState hgs) buf.writestring(" = "); if (stcToBuffer(buf, d.storage_class)) buf.writeByte(' '); - typeToBuffer(d.type, null, buf, &hgs); + typeToBuffer(d.type, null, buf, hgs); hgs.declstring = false; } buf.writeByte(';'); @@ -1689,7 +1689,7 @@ void toCBuffer(Dsymbol s, ref OutBuffer buf, ref HdrGenState hgs) if (d.aliassym) toCBuffer(d.aliassym, buf, hgs); else // d.type - typeToBuffer(d.type, null, buf, &hgs); + typeToBuffer(d.type, null, buf, hgs); buf.writeByte(';'); buf.writenl(); } @@ -1709,7 +1709,7 @@ void toCBuffer(Dsymbol s, ref OutBuffer buf, ref HdrGenState hgs) if (stcToBuffer(buf, f.storage_class)) buf.writeByte(' '); auto tf = f.type.isTypeFunction(); - typeToBuffer(tf, f.ident, buf, &hgs); + typeToBuffer(tf, f.ident, buf, hgs); if (hgs.hdrgen) { @@ -1757,8 +1757,8 @@ void toCBuffer(Dsymbol s, ref OutBuffer buf, ref HdrGenState hgs) TypeFunction tf = cast(TypeFunction)f.type; if (!f.inferRetType && tf.next) - typeToBuffer(tf.next, null, buf, &hgs); - parametersToBuffer(tf.parameterList, buf, &hgs); + typeToBuffer(tf.next, null, buf, hgs); + parametersToBuffer(tf.parameterList, buf, hgs); // https://issues.dlang.org/show_bug.cgi?id=20074 void printAttribute(string str) @@ -1781,7 +1781,7 @@ void toCBuffer(Dsymbol s, ref OutBuffer buf, ref HdrGenState hgs) if (rs && rs.exp) { buf.writestring(" => "); - rs.exp.expressionToBuffer(buf, &hgs); + rs.exp.expressionToBuffer(buf, hgs); } else { @@ -1850,7 +1850,7 @@ void toCBuffer(Dsymbol s, ref OutBuffer buf, ref HdrGenState hgs) { assert(es.exp && es.exp.op == EXP.assert_); buf.writestring(" ("); - (cast(AssertExp)es.exp).e1.expressionToBuffer(buf, &hgs); + (cast(AssertExp)es.exp).e1.expressionToBuffer(buf, hgs); buf.writestring(");"); buf.writenl(); } @@ -1875,9 +1875,9 @@ void toCBuffer(Dsymbol s, ref OutBuffer buf, ref HdrGenState hgs) if (stcToBuffer(buf, d.storage_class)) buf.writeByte(' '); Identifier id = d.isAnonymous() ? null : d.ident; - typeToBuffer(d.type, id, buf, &hgs); + typeToBuffer(d.type, id, buf, hgs); buf.writestring(" : "); - d.width.expressionToBuffer(buf, &hgs); + d.width.expressionToBuffer(buf, hgs); buf.writeByte(';'); buf.writenl(); } @@ -1980,9 +1980,9 @@ private void visitVarDecl(VarDeclaration v, bool anywritten, ref OutBuffer buf, { auto ie = v._init.isExpInitializer(); if (ie && (ie.exp.op == EXP.construct || ie.exp.op == EXP.blit)) - (cast(AssignExp)ie.exp).e2.expressionToBuffer(buf, &hgs); + (cast(AssignExp)ie.exp).e2.expressionToBuffer(buf, hgs); else - v._init.initializerToBuffer(buf, &hgs); + v._init.initializerToBuffer(buf, hgs); } const commentIt = hgs.importcHdr && isSpecialCName(v.ident); @@ -2005,7 +2005,7 @@ private void visitVarDecl(VarDeclaration v, bool anywritten, ref OutBuffer buf, if (stcToBuffer(buf, stc)) buf.writeByte(' '); if (v.type) - typeToBuffer(v.type, v.ident, buf, &hgs); + typeToBuffer(v.type, v.ident, buf, hgs); else if (useTypeof) { buf.writestring("typeof("); @@ -2050,7 +2050,7 @@ private bool isSpecialCName(Identifier id) /********************************************* * Print expression to buffer. */ -private void expressionPrettyPrint(Expression e, ref OutBuffer buf, HdrGenState* hgs) +private void expressionPrettyPrint(Expression e, ref OutBuffer buf, ref HdrGenState hgs) { void visit(Expression e) { @@ -2303,7 +2303,7 @@ private void expressionPrettyPrint(Expression e, ref OutBuffer buf, HdrGenState* { e.sds.dsymbolToBuffer(buf, hgs); } - else if (hgs !is null && hgs.ddoc) + else if (hgs.ddoc) { // fixes bug 6491 if (auto m = e.sds.isModule()) @@ -2420,7 +2420,7 @@ private void expressionPrettyPrint(Expression e, ref OutBuffer buf, HdrGenState* // which isn't correct as regular D code. buf.writeByte('('); - visitVarDecl(var, false, buf, *hgs); + visitVarDecl(var, false, buf, hgs); buf.writeByte(';'); buf.writeByte(')'); @@ -2476,7 +2476,7 @@ private void expressionPrettyPrint(Expression e, ref OutBuffer buf, HdrGenState* if (e.parameters && e.parameters.length) { buf.writestring(", "); - visitTemplateParameters(e.parameters, buf, *hgs); + visitTemplateParameters(e.parameters, buf, hgs); } buf.writeByte(')'); } @@ -2954,12 +2954,12 @@ public: if (tp.specType) { buf.writestring(" : "); - typeToBuffer(tp.specType, null, *buf, hgs); + typeToBuffer(tp.specType, null, *buf, *hgs); } if (tp.defaultType) { buf.writestring(" = "); - typeToBuffer(tp.defaultType, null, *buf, hgs); + typeToBuffer(tp.defaultType, null, *buf, *hgs); } } @@ -2973,33 +2973,33 @@ public: { buf.writestring("alias "); if (tp.specType) - typeToBuffer(tp.specType, tp.ident, *buf, hgs); + typeToBuffer(tp.specType, tp.ident, *buf, *hgs); else buf.writestring(tp.ident.toString()); if (tp.specAlias) { buf.writestring(" : "); - objectToBuffer(tp.specAlias, *buf, hgs); + objectToBuffer(tp.specAlias, *buf, *hgs); } if (tp.defaultAlias) { buf.writestring(" = "); - objectToBuffer(tp.defaultAlias, *buf, hgs); + objectToBuffer(tp.defaultAlias, *buf, *hgs); } } override void visit(TemplateValueParameter tp) { - typeToBuffer(tp.valType, tp.ident, *buf, hgs); + typeToBuffer(tp.valType, tp.ident, *buf, *hgs); if (tp.specValue) { buf.writestring(" : "); - tp.specValue.expressionToBuffer(*buf, hgs); + tp.specValue.expressionToBuffer(*buf, *hgs); } if (tp.defaultValue) { buf.writestring(" = "); - tp.defaultValue.expressionToBuffer(*buf, hgs); + tp.defaultValue.expressionToBuffer(*buf, *hgs); } } @@ -3010,9 +3010,9 @@ public: } } -private void conditionToBuffer(Condition c, ref OutBuffer buf, HdrGenState* hgs) +private void conditionToBuffer(Condition c, ref OutBuffer buf, ref HdrGenState hgs) { - scope v = new ConditionPrettyPrintVisitor(&buf, hgs); + scope v = new ConditionPrettyPrintVisitor(&buf, &hgs); c.accept(v); } @@ -3052,19 +3052,19 @@ public: override void visit(StaticIfCondition c) { buf.writestring("static if ("); - c.exp.expressionToBuffer(*buf, hgs); + c.exp.expressionToBuffer(*buf, *hgs); buf.writeByte(')'); } } void toCBuffer(const Statement s, ref OutBuffer buf, ref HdrGenState hgs) { - (cast()s).statementToBuffer(buf, &hgs); + (cast()s).statementToBuffer(buf, hgs); } void toCBuffer(const Type t, ref OutBuffer buf, const Identifier ident, ref HdrGenState hgs) { - typeToBuffer(cast() t, ident, buf, &hgs); + typeToBuffer(cast() t, ident, buf, hgs); } // used from TemplateInstance::toChars() and TemplateMixin::toChars() @@ -3074,12 +3074,12 @@ void toCBufferInstance(const TemplateInstance ti, ref OutBuffer buf, bool qualif hgs.fullQual = qualifyTypes; buf.writestring(ti.name.toChars()); - tiargsToBuffer(cast() ti, buf, &hgs); + tiargsToBuffer(cast() ti, buf, hgs); } void toCBuffer(const Initializer iz, ref OutBuffer buf, ref HdrGenState hgs) { - initializerToBuffer(cast() iz, buf, &hgs); + initializerToBuffer(cast() iz, buf, hgs); } bool stcToBuffer(ref OutBuffer buf, StorageClass stc) @safe @@ -3275,19 +3275,19 @@ extern (D) string visibilityToString(Visibility.Kind kind) nothrow pure @safe void functionToBufferFull(TypeFunction tf, ref OutBuffer buf, const Identifier ident, ref HdrGenState hgs, TemplateDeclaration td) { //printf("TypeFunction::toCBuffer() this = %p\n", this); - visitFuncIdentWithPrefix(tf, ident, td, buf, &hgs); + visitFuncIdentWithPrefix(tf, ident, td, buf, hgs); } // ident is inserted before the argument list and will be "function" or "delegate" for a type void functionToBufferWithIdent(TypeFunction tf, ref OutBuffer buf, const(char)* ident, bool isStatic) { HdrGenState hgs; - visitFuncIdentWithPostfix(tf, ident.toDString(), buf, &hgs, isStatic); + visitFuncIdentWithPostfix(tf, ident.toDString(), buf, hgs, isStatic); } void toCBuffer(const Expression e, ref OutBuffer buf, ref HdrGenState hgs) { - expressionPrettyPrint(cast()e, buf, &hgs); + expressionPrettyPrint(cast()e, buf, hgs); } /************************************************** @@ -3302,7 +3302,7 @@ void argExpTypesToCBuffer(ref OutBuffer buf, Expressions* arguments) { if (i) buf.writestring(", "); - typeToBuffer(arg.type, null, buf, &hgs); + typeToBuffer(arg.type, null, buf, hgs); } } @@ -3315,7 +3315,7 @@ void arrayObjectsToBuffer(ref OutBuffer buf, Objects* objects) { if (i) buf.writestring(", "); - objectToBuffer(o, buf, &hgs); + objectToBuffer(o, buf, hgs); } } @@ -3329,7 +3329,7 @@ extern (C++) const(char)* parametersTypeToChars(ParameterList pl) { OutBuffer buf; HdrGenState hgs; - parametersToBuffer(pl, buf, &hgs); + parametersToBuffer(pl, buf, hgs); return buf.extractChars(); } @@ -3347,7 +3347,7 @@ const(char)* parameterToChars(Parameter parameter, TypeFunction tf, bool fullQua HdrGenState hgs; hgs.fullQual = fullQual; - parameterToBuffer(parameter, buf, &hgs); + parameterToBuffer(parameter, buf, hgs); if (tf.parameterList.varargs == VarArg.typesafe && parameter == tf.parameterList[tf.parameterList.parameters.length - 1]) { @@ -3365,7 +3365,7 @@ const(char)* parameterToChars(Parameter parameter, TypeFunction tf, bool fullQua * hgs = context */ -private void parametersToBuffer(ParameterList pl, ref OutBuffer buf, HdrGenState* hgs) +private void parametersToBuffer(ParameterList pl, ref OutBuffer buf, ref HdrGenState hgs) { buf.writeByte('('); foreach (i; 0 .. pl.length) @@ -3403,7 +3403,7 @@ private void parametersToBuffer(ParameterList pl, ref OutBuffer buf, HdrGenState * buf = buffer to write it to * hgs = context */ -private void parameterToBuffer(Parameter p, ref OutBuffer buf, HdrGenState* hgs) +private void parameterToBuffer(Parameter p, ref OutBuffer buf, ref HdrGenState hgs) { if (p.userAttribDecl) { @@ -3475,7 +3475,7 @@ private void parameterToBuffer(Parameter p, ref OutBuffer buf, HdrGenState* hgs) * basis = replace `null`s in argument list with this expression (for sparse array literals) * names = if non-null, use these as the names for the arguments */ -private void argsToBuffer(Expressions* expressions, ref OutBuffer buf, HdrGenState* hgs, Expression basis = null, Identifiers* names = null) +private void argsToBuffer(Expressions* expressions, ref OutBuffer buf, ref HdrGenState hgs, Expression basis = null, Identifiers* names = null) { if (!expressions || !expressions.length) return; @@ -3526,7 +3526,7 @@ private void argsToBuffer(Expressions* expressions, ref OutBuffer buf, HdrGenSta } } -private void sizeToBuffer(Expression e, ref OutBuffer buf, HdrGenState* hgs) +private void sizeToBuffer(Expression e, ref OutBuffer buf, ref HdrGenState hgs) { if (e.type == Type.tsize_t) { @@ -3554,7 +3554,7 @@ private void sizeToBuffer(Expression e, ref OutBuffer buf, HdrGenState* hgs) expToBuffer(e, PREC.assign, buf, hgs); } -private void expressionToBuffer(Expression e, ref OutBuffer buf, HdrGenState* hgs) +private void expressionToBuffer(Expression e, ref OutBuffer buf, ref HdrGenState hgs) { expressionPrettyPrint(e, buf, hgs); } @@ -3563,7 +3563,7 @@ private void expressionToBuffer(Expression e, ref OutBuffer buf, HdrGenState* hg * Write expression out to buf, but wrap it * in ( ) if its precedence is less than pr. */ -private void expToBuffer(Expression e, PREC pr, ref OutBuffer buf, HdrGenState* hgs) +private void expToBuffer(Expression e, PREC pr, ref OutBuffer buf, ref HdrGenState hgs) { debug { @@ -3597,7 +3597,7 @@ private void expToBuffer(Expression e, PREC pr, ref OutBuffer buf, HdrGenState* /************************************************** * An entry point to pretty-print type. */ -private void typeToBuffer(Type t, const Identifier ident, ref OutBuffer buf, HdrGenState* hgs, +private void typeToBuffer(Type t, const Identifier ident, ref OutBuffer buf, ref HdrGenState hgs, ubyte modMask = 0) { if (auto tf = t.isTypeFunction()) @@ -3613,7 +3613,7 @@ private void typeToBuffer(Type t, const Identifier ident, ref OutBuffer buf, Hdr } } -private void visitWithMask(Type t, ubyte modMask, ref OutBuffer buf, HdrGenState* hgs) +private void visitWithMask(Type t, ubyte modMask, ref OutBuffer buf, ref HdrGenState hgs) { // Tuples and functions don't use the type constructor syntax if (modMask == t.mod || t.ty == Tfunction || t.ty == Ttuple) @@ -3649,7 +3649,7 @@ private void visitWithMask(Type t, ubyte modMask, ref OutBuffer buf, HdrGenState } -private void dumpTemplateInstance(TemplateInstance ti, ref OutBuffer buf, HdrGenState* hgs) +private void dumpTemplateInstance(TemplateInstance ti, ref OutBuffer buf, ref HdrGenState hgs) { buf.writeByte('{'); buf.writenl(); @@ -3672,7 +3672,7 @@ private void dumpTemplateInstance(TemplateInstance ti, ref OutBuffer buf, HdrGen } -private void tiargsToBuffer(TemplateInstance ti, ref OutBuffer buf, HdrGenState* hgs) +private void tiargsToBuffer(TemplateInstance ti, ref OutBuffer buf, ref HdrGenState hgs) { buf.writeByte('!'); if (ti.nest) @@ -3721,7 +3721,7 @@ private void tiargsToBuffer(TemplateInstance ti, ref OutBuffer buf, HdrGenState* * This makes a 'pretty' version of the template arguments. * It's analogous to genIdent() which makes a mangled version. */ -private void objectToBuffer(RootObject oarg, ref OutBuffer buf, HdrGenState* hgs) +private void objectToBuffer(RootObject oarg, ref OutBuffer buf, ref HdrGenState hgs) { //printf("objectToBuffer()\n"); /* The logic of this should match what genIdent() does. The _dynamic_cast() @@ -3774,7 +3774,7 @@ private void objectToBuffer(RootObject oarg, ref OutBuffer buf, HdrGenState* hgs } -private void visitFuncIdentWithPostfix(TypeFunction t, const char[] ident, ref OutBuffer buf, HdrGenState* hgs, bool isStatic) +private void visitFuncIdentWithPostfix(TypeFunction t, const char[] ident, ref OutBuffer buf, ref HdrGenState hgs, bool isStatic) { if (t.inuse) { @@ -3819,7 +3819,7 @@ private void visitFuncIdentWithPostfix(TypeFunction t, const char[] ident, ref O } private void visitFuncIdentWithPrefix(TypeFunction t, const Identifier ident, TemplateDeclaration td, - ref OutBuffer buf, HdrGenState* hgs) + ref OutBuffer buf, ref HdrGenState hgs) { if (t.inuse) { @@ -3875,7 +3875,7 @@ private void visitFuncIdentWithPrefix(TypeFunction t, const Identifier ident, Te { if (i) buf.writestring(", "); - toCBuffer(p, buf, *hgs); + toCBuffer(p, buf, hgs); } buf.writeByte(')'); } @@ -3888,7 +3888,7 @@ private void visitFuncIdentWithPrefix(TypeFunction t, const Identifier ident, Te } -private void initializerToBuffer(Initializer inx, ref OutBuffer buf, HdrGenState* hgs) +private void initializerToBuffer(Initializer inx, ref OutBuffer buf, ref HdrGenState hgs) { void visitError(ErrorInitializer iz) { @@ -3961,7 +3961,7 @@ private void initializerToBuffer(Initializer inx, ref OutBuffer buf, HdrGenState if (d.exp) { buf.writeByte('['); - toCBuffer(d.exp, buf, *hgs); + toCBuffer(d.exp, buf, hgs); buf.writeByte(']'); } else @@ -3982,7 +3982,7 @@ private void initializerToBuffer(Initializer inx, ref OutBuffer buf, HdrGenState } -private void typeToBufferx(Type t, ref OutBuffer buf, HdrGenState* hgs) +private void typeToBufferx(Type t, ref OutBuffer buf, ref HdrGenState hgs) { void visitType(Type t) { From d0b54bdea820fe800e6688f3cf4e558ddf4f41e3 Mon Sep 17 00:00:00 2001 From: Walter Bright Date: Thu, 21 Dec 2023 02:14:17 -0800 Subject: [PATCH 143/215] move Expression.toChars() to hdrgen.d (dlang/dmd!15937) --- dmd/expression.d | 5 +---- dmd/frontend.h | 2 ++ dmd/hdrgen.d | 8 ++++++++ 3 files changed, 11 insertions(+), 4 deletions(-) diff --git a/dmd/expression.d b/dmd/expression.d index f51a8b00891..ea12a73ae46 100644 --- a/dmd/expression.d +++ b/dmd/expression.d @@ -420,10 +420,7 @@ extern (C++) abstract class Expression : ASTNode override const(char)* toChars() const { - OutBuffer buf; - HdrGenState hgs; - toCBuffer(this, buf, hgs); - return buf.extractChars(); + return .toChars(this); } /********************************** diff --git a/dmd/frontend.h b/dmd/frontend.h index 7e970735d5e..68c7f16d9bd 100644 --- a/dmd/frontend.h +++ b/dmd/frontend.h @@ -8000,6 +8000,8 @@ extern Expression* toLvalue(Expression* _this, Scope* sc, const char* action); extern Expression* modifiableLvalue(Expression* _this, Scope* sc); +extern const char* toChars(const Expression* const e); + extern const char* toChars(const Initializer* const i); extern const char* toChars(const Type* const t); diff --git a/dmd/hdrgen.d b/dmd/hdrgen.d index 5820336a068..cdaad5d4a44 100644 --- a/dmd/hdrgen.d +++ b/dmd/hdrgen.d @@ -112,6 +112,14 @@ public extern (C++) const(char)* toChars(const Statement s) return buf.extractSlice().ptr; } +public extern (C++) const(char)* toChars(const Expression e) +{ + HdrGenState hgs; + OutBuffer buf; + toCBuffer(e, buf, hgs); + return buf.extractChars(); +} + public extern (C++) const(char)* toChars(const Initializer i) { OutBuffer buf; From 62d7835fb38f7f44c69c810c7fca50ad8d8f1e94 Mon Sep 17 00:00:00 2001 From: Martin Kinkelin Date: Thu, 21 Dec 2023 20:27:41 +0100 Subject: [PATCH 144/215] druntime Makefile: Remove DMD_DIR variable This looks like a leftover from when druntime was a separate repo. Additionally, the semantics (`/compiler`) diverges from DMD_DIR used by Phobos and dlang.org Makefiles (``), as well as CI scripts. --- runtime/druntime/Makefile | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/runtime/druntime/Makefile b/runtime/druntime/Makefile index ed69d01670e..06f39779806 100644 --- a/runtime/druntime/Makefile +++ b/runtime/druntime/Makefile @@ -15,11 +15,10 @@ QUIET:= -DMD_DIR=../compiler DUB=dub TOOLS_DIR=../../tools -include $(DMD_DIR)/src/osmodel.mak +include ../compiler/src/osmodel.mak ifeq (windows,$(OS)) DOTEXE:=.exe @@ -51,7 +50,7 @@ ifneq ($(BUILD),release) endif endif -DMD=$(DMD_DIR)/../generated/$(OS)/$(BUILD)/$(MODEL)/dmd$(DOTEXE) +DMD=../generated/$(OS)/$(BUILD)/$(MODEL)/dmd$(DOTEXE) INSTALL_DIR=../../install # directory where the html files for the documentation are placed @@ -364,11 +363,11 @@ $(IMPDIR)/%.h : src/%.h ######################## Build DMD if non-existent ############################## -$(DMD_DIR)/../generated/$(OS)/$(BUILD)/$(MODEL)/dmd$(DOTEXE): - $(MAKE) -C $(DMD_DIR)/.. dmd BUILD=$(BUILD) OS=$(OS) MODEL=$(MODEL) DMD="" +../generated/$(OS)/$(BUILD)/$(MODEL)/dmd$(DOTEXE): + $(MAKE) -C .. dmd BUILD=$(BUILD) OS=$(OS) MODEL=$(MODEL) DMD="" # alias using the absolute path (the Phobos Makefile specifies an absolute path) -$(abspath $(DMD_DIR)/../generated/$(OS)/$(BUILD)/$(MODEL)/dmd$(DOTEXE)): $(DMD_DIR)/../generated/$(OS)/$(BUILD)/$(MODEL)/dmd$(DOTEXE) +$(abspath ../generated/$(OS)/$(BUILD)/$(MODEL)/dmd$(DOTEXE)): ../generated/$(OS)/$(BUILD)/$(MODEL)/dmd$(DOTEXE) ################### C/ASM Targets ############################ From 75cb4da78bb3217108d37c7609e8d34c10fb40ff Mon Sep 17 00:00:00 2001 From: Tim Schendekehl Date: Thu, 21 Dec 2023 13:21:47 +0100 Subject: [PATCH 145/215] Fixes issues 20339, 24292: Calculate isPOD without information from semantic run Issue 20339: isPOD returns true if sizeof is accessed inside struct declaration Issue 24292: Struct with destructor wrongly returned in register Function StructDeclaration.isPOD can be called before the semantic run for the struct is finished. It then uses incomplete information about destructors, postblits and copy constructors. The result of isPOD is cached, so later calls will also return the wrong result. This commit changes isPOD, so it uses variables, which are already filled before the semantic run. --- dmd/clone.d | 2 +- dmd/dstruct.d | 6 ++- tests/dmd/compilable/issue20339.d | 44 ++++++++++++++++ .../runnable_cxx/extra-files/test24292.cpp | 46 +++++++++++++++++ tests/dmd/runnable_cxx/test24292.d | 50 +++++++++++++++++++ 5 files changed, 146 insertions(+), 2 deletions(-) create mode 100644 tests/dmd/compilable/issue20339.d create mode 100644 tests/dmd/runnable_cxx/extra-files/test24292.cpp create mode 100644 tests/dmd/runnable_cxx/test24292.d diff --git a/dmd/clone.d b/dmd/clone.d index ca7f398ae7a..e4060d4e392 100644 --- a/dmd/clone.d +++ b/dmd/clone.d @@ -1571,7 +1571,7 @@ private Statement generateCopyCtorBody(StructDeclaration sd) * `true` if one needs to be generated * `false` otherwise */ -private bool needCopyCtor(StructDeclaration sd, out bool hasCpCtor) +bool needCopyCtor(StructDeclaration sd, out bool hasCpCtor) { if (global.errors) return false; diff --git a/dmd/dstruct.d b/dmd/dstruct.d index 0e0a1f52f88..49411c69754 100644 --- a/dmd/dstruct.d +++ b/dmd/dstruct.d @@ -434,7 +434,11 @@ extern (C++) class StructDeclaration : AggregateDeclaration ispod = ThreeState.yes; - if (enclosing || postblit || dtor || hasCopyCtor) + import dmd.clone; + bool hasCpCtorLocal; + needCopyCtor(this, hasCpCtorLocal); + + if (enclosing || search(this, loc, Id.postblit) || search(this, loc, Id.dtor) || hasCpCtorLocal) { ispod = ThreeState.no; return false; diff --git a/tests/dmd/compilable/issue20339.d b/tests/dmd/compilable/issue20339.d new file mode 100644 index 00000000000..3d5bdd80a02 --- /dev/null +++ b/tests/dmd/compilable/issue20339.d @@ -0,0 +1,44 @@ +/* +TEST_OUTPUT: +--- +4 +false +false +--- +*/ + +// https://issues.dlang.org/show_bug.cgi?id=20339 + +struct S +{ + pragma(msg, cast(int)S.sizeof); + + this(this){} + ~this(){} + + int f; +} + +static assert(__traits(isPOD, S) == false); + + +pragma(msg, __traits(isPOD, T)); + +struct T +{ + this(this){} + ~this(){} +} + +static assert(__traits(isPOD, T) == false); + + +struct U +{ + pragma(msg, __traits(isPOD, U)); + + this(this){} + ~this(){} +} + +static assert(__traits(isPOD, U) == false); diff --git a/tests/dmd/runnable_cxx/extra-files/test24292.cpp b/tests/dmd/runnable_cxx/extra-files/test24292.cpp new file mode 100644 index 00000000000..2fab9afbbd8 --- /dev/null +++ b/tests/dmd/runnable_cxx/extra-files/test24292.cpp @@ -0,0 +1,46 @@ +template +struct List +{ + T* begin; +}; + +struct StructWithDestructor +{ + ~StructWithDestructor(); + + int i; +}; + +struct StructWithCopyCtor +{ + StructWithCopyCtor(); + StructWithCopyCtor(const StructWithCopyCtor &other); + + int i; +}; + +StructWithDestructor::~StructWithDestructor() +{ +} + +StructWithCopyCtor::StructWithCopyCtor() +{ +} + +StructWithCopyCtor::StructWithCopyCtor(const StructWithCopyCtor &other) : i(other.i) +{ +} + +StructWithDestructor getStructWithDestructor() +{ + StructWithDestructor r; + r.i = 12345; + return r; +} + +StructWithCopyCtor getStructWithCopyCtor() +{ + StructWithCopyCtor r; + r.i = 54321; + return r; +} diff --git a/tests/dmd/runnable_cxx/test24292.d b/tests/dmd/runnable_cxx/test24292.d new file mode 100644 index 00000000000..b71f925639c --- /dev/null +++ b/tests/dmd/runnable_cxx/test24292.d @@ -0,0 +1,50 @@ +// EXTRA_CPP_SOURCES: test24292.cpp + +extern(C++) struct List(T) +{ + // Any of the following static ifs can trigger the problem. + static if (T.sizeof > 4) {} + static if (__traits(isZeroInit, T)) {} + static if (__traits(isPOD, T)) {} + + T* begin; +} + +extern(C++) struct StructWithDestructor +{ + ~this(); + + alias L = List!StructWithDestructor; + int i; +} + +extern(C++) struct StructWithCopyCtor +{ + this(ref const(StructWithCopyCtor)); + + alias L = List!StructWithCopyCtor; + int i; +} + +extern(D) struct StructWithPostblit +{ + this(this) {} + + alias L = List!StructWithPostblit; + int i; +} + +static assert(!__traits(isPOD, StructWithDestructor)); +static assert(!__traits(isPOD, StructWithCopyCtor)); +static assert(!__traits(isPOD, StructWithPostblit)); + +extern(C++) StructWithDestructor getStructWithDestructor(); +extern(C++) StructWithCopyCtor getStructWithCopyCtor(); + +void main() +{ + StructWithDestructor structWithDestructor = getStructWithDestructor(); + assert(structWithDestructor.i == 12345); + StructWithCopyCtor structWithCopyCtor = getStructWithCopyCtor(); + assert(structWithCopyCtor.i == 54321); +} From 290fa4fc06c2a5d3cfdf4dfd7162cc42a8b0f983 Mon Sep 17 00:00:00 2001 From: Walter Bright Date: Thu, 21 Dec 2023 20:37:29 -0800 Subject: [PATCH 146/215] Replace previewIn with STC.inscoperef) (dlang/dmd!15935) --- dmd/astenums.d | 4 +- dmd/declaration.h | 2 +- dmd/dmangle.d | 2 +- dmd/dsymbolsem.d | 2 +- dmd/frontend.h | 2222 +++++++++++++++++++++++---------------------- dmd/hdrgen.d | 2 +- dmd/mtype.d | 22 +- dmd/parse.d | 8 +- dmd/typesem.d | 12 +- 9 files changed, 1137 insertions(+), 1139 deletions(-) diff --git a/dmd/astenums.d b/dmd/astenums.d index 6a9c0104a72..4632959ac99 100644 --- a/dmd/astenums.d +++ b/dmd/astenums.d @@ -63,7 +63,7 @@ enum STC : ulong // transfer changes to declaration.h foreach_ = 0x4000, /// variable for foreach loop variadic = 0x8000, /// the `variadic` parameter in: T foo(T a, U b, V variadic...) - // = 0x1_0000, + constscoperef = 0x1_0000, /// when `in` means const|scope|ref templateparameter = 0x2_0000, /// template parameter ref_ = 0x4_0000, /// `ref` scope_ = 0x8_0000, /// `scope` @@ -112,7 +112,7 @@ enum STC : ulong // transfer changes to declaration.h volatile_ = 0x40_0000_0000_0000, /// destined for volatile in the back end safeGroup = STC.safe | STC.trusted | STC.system, - IOR = STC.in_ | STC.ref_ | STC.out_, + IOR = STC.constscoperef | STC.in_ | STC.ref_ | STC.out_, TYPECTOR = (STC.const_ | STC.immutable_ | STC.shared_ | STC.wild), FUNCATTR = (STC.ref_ | STC.nothrow_ | STC.nogc | STC.pure_ | STC.property | STC.live | safeGroup), diff --git a/dmd/declaration.h b/dmd/declaration.h index adbc26bf570..83474736f71 100644 --- a/dmd/declaration.h +++ b/dmd/declaration.h @@ -54,7 +54,7 @@ struct AttributeViolation; #define STCforeach 0x4000ULL /// variable for foreach loop #define STCvariadic 0x8000ULL /// the `variadic` parameter in: T foo(T a, U b, V variadic...) - // 0x10000ULL + #define STCconstscoperef 0x10000ULL /// when `in` means const|scope|ref #define STCtemplateparameter 0x20000ULL /// template parameter #define STCref 0x40000ULL /// `ref` #define STCscope 0x80000ULL /// `scope` diff --git a/dmd/dmangle.d b/dmd/dmangle.d index 2bedccb71c1..afd139ccb15 100644 --- a/dmd/dmangle.d +++ b/dmd/dmangle.d @@ -528,7 +528,7 @@ void mangleParameter(Parameter p, ref OutBuffer buf, ref Backref backref) if (stc & STC.return_) buf.writestring("Nk"); // return - switch (stc & (STC.IOR | STC.lazy_)) + switch (stc & ((STC.IOR | STC.lazy_) & ~STC.constscoperef)) { case 0: break; diff --git a/dmd/dsymbolsem.d b/dmd/dsymbolsem.d index 1d5d11a3c09..3e1a5af719d 100644 --- a/dmd/dsymbolsem.d +++ b/dmd/dsymbolsem.d @@ -947,7 +947,7 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor // At this point we can add `scope` to the STC instead of `in`, // because we are never going to use this variable's STC for user messages - if (dsym.storage_class & STC.in_ && global.params.previewIn) + if (dsym.storage_class & STC.constscoperef) dsym.storage_class |= STC.scope_; if (dsym.storage_class & STC.scope_) diff --git a/dmd/frontend.h b/dmd/frontend.h index 68c7f16d9bd..b55cfb49380 100644 --- a/dmd/frontend.h +++ b/dmd/frontend.h @@ -308,7 +308,6 @@ class StructInitializer; class ArrayInitializer; class ExpInitializer; class CInitializer; -class FileManager; class ErrorStatement; class ExpStatement; class ConditionalStatement; @@ -329,6 +328,8 @@ class InlineAsmStatement; class GccAsmStatement; class ImportStatement; struct Token; +struct Param; +class FileManager; class Object; class TypeInfo_Class; class TypeInfo; @@ -4221,666 +4222,132 @@ enum : int32_t { LOGDEFAULTINIT = 0 }; enum : int32_t { LOGDOTEXP = 0 }; -enum class DiagnosticReporting : uint8_t +class Parameter final : public ASTNode { - error = 0u, - inform = 1u, - off = 2u, +public: + Loc loc; + StorageClass storageClass; + Type* type; + Identifier* ident; + Expression* defaultArg; + UserAttributeDeclaration* userAttribDecl; + static Parameter* create(const Loc& loc, StorageClass storageClass, Type* type, Identifier* ident, Expression* defaultArg, UserAttributeDeclaration* userAttribDecl); + Parameter* syntaxCopy(); + Type* isLazyArray(); + bool isLazy() const; + bool isReference() const; + DYNCAST dyncast() const override; + void accept(Visitor* v) override; + static size_t dim(Array* parameters); + static Parameter* getNth(Array* parameters, size_t nth); + const char* toChars() const override; + bool isCovariant(bool returnByRef, const Parameter* const p) const; }; -enum class CppStdRevision : uint32_t +enum class RET { - cpp98 = 199711u, - cpp11 = 201103u, - cpp14 = 201402u, - cpp17 = 201703u, - cpp20 = 202002u, + regs = 1, + stack = 2, }; -struct Help final +enum : uint64_t { SIZE_INVALID = 18446744073709551615LLU }; + +enum class ScopeRef { - bool manual; - bool usage; - bool mcpu; - bool transition; - bool check; - bool checkAction; - bool revert; - bool preview; - bool externStd; - bool hc; - Help() : - manual(), - usage(), - mcpu(), - transition(), - check(), - checkAction(), - revert(), - preview(), - externStd(), - hc() - { - } - Help(bool manual, bool usage = false, bool mcpu = false, bool transition = false, bool check = false, bool checkAction = false, bool revert = false, bool preview = false, bool externStd = false, bool hc = false) : - manual(manual), - usage(usage), - mcpu(mcpu), - transition(transition), - check(check), - checkAction(checkAction), - revert(revert), - preview(preview), - externStd(externStd), - hc(hc) - {} + None = 0, + Scope = 1, + ReturnScope = 2, + Ref = 3, + ReturnRef = 4, + RefScope = 5, + ReturnRef_Scope = 6, + Ref_ReturnScope = 7, + Return = 8, }; -struct Verbose final +enum class TRUSTformat { - bool verbose; - bool showColumns; - bool tls; - bool templates; - bool templatesListInstances; - bool gc; - bool field; - bool complex; - bool vin; - bool showGaggedErrors; - bool printErrorContext; - bool logo; - bool color; - bool cov; - MessageStyle messageStyle; - uint32_t errorLimit; - uint32_t errorSupplementLimit; - uint32_t errorSupplementCount(); - Verbose() : - verbose(), - showColumns(), - tls(), - templates(), - templatesListInstances(), - gc(), - field(), - complex(true), - vin(), - showGaggedErrors(), - printErrorContext(), - logo(), - color(), - cov(), - messageStyle((MessageStyle)0u), - errorLimit(20u), - errorSupplementLimit(6u) - { - } - Verbose(bool verbose, bool showColumns = false, bool tls = false, bool templates = false, bool templatesListInstances = false, bool gc = false, bool field = false, bool complex = true, bool vin = false, bool showGaggedErrors = false, bool printErrorContext = false, bool logo = false, bool color = false, bool cov = false, MessageStyle messageStyle = (MessageStyle)0u, uint32_t errorLimit = 20u, uint32_t errorSupplementLimit = 6u) : - verbose(verbose), - showColumns(showColumns), - tls(tls), - templates(templates), - templatesListInstances(templatesListInstances), - gc(gc), - field(field), - complex(complex), - vin(vin), - showGaggedErrors(showGaggedErrors), - printErrorContext(printErrorContext), - logo(logo), - color(color), - cov(cov), - messageStyle(messageStyle), - errorLimit(errorLimit), - errorSupplementLimit(errorSupplementLimit) - {} + TRUSTformatDefault = 0, + TRUSTformatSystem = 1, }; -enum class FeatureState : uint8_t +class TypeNext : public Type { - default_ = 0u, - disabled = 1u, - enabled = 2u, +public: + Type* next; + int32_t hasWild() const final override; + Type* nextOf() final override; + Type* makeConst() final override; + Type* makeImmutable() final override; + Type* makeShared() final override; + Type* makeSharedConst() final override; + Type* makeWild() final override; + Type* makeWildConst() final override; + Type* makeSharedWild() final override; + Type* makeSharedWildConst() final override; + Type* makeMutable() final override; + MATCH constConv(Type* to) override; + uint8_t deduceWild(Type* t, bool isRef) final override; + void transitive(); + void accept(Visitor* v) override; }; -enum class CHECKENABLE : uint8_t +class TypeArray : public TypeNext { - _default = 0u, - off = 1u, - on = 2u, - safeonly = 3u, +public: + void accept(Visitor* v) override; }; -enum class CHECKACTION : uint8_t +class TypeAArray final : public TypeArray { - D = 0u, - C = 1u, - halt = 2u, - context = 3u, +public: + Type* index; + Loc loc; + static TypeAArray* create(Type* t, Type* index); + const char* kind() const override; + TypeAArray* syntaxCopy() override; + uinteger_t size(const Loc& loc) override; + bool isZeroInit(const Loc& loc) override; + bool isBoolean() override; + bool hasPointers() override; + MATCH implicitConvTo(Type* to) override; + MATCH constConv(Type* to) override; + void accept(Visitor* v) override; }; -struct Output final +class TypeBasic final : public Type { - bool doOutput; - bool fullOutput; - _d_dynamicArray< const char > dir; - _d_dynamicArray< const char > name; - Array files; - OutBuffer* buffer; - int32_t bufferLines; - Output() : - doOutput(), - fullOutput(), - dir(), - name(), - files(), - buffer(), - bufferLines() - { - } - Output(bool doOutput, bool fullOutput = false, _d_dynamicArray< const char > dir = {}, _d_dynamicArray< const char > name = {}, Array files = Array(), OutBuffer* buffer = nullptr, int32_t bufferLines = 0) : - doOutput(doOutput), - fullOutput(fullOutput), - dir(dir), - name(name), - files(files), - buffer(buffer), - bufferLines(bufferLines) - {} +public: + const char* dstring; + uint32_t flags; + const char* kind() const override; + TypeBasic* syntaxCopy() override; + uinteger_t size(const Loc& loc) override; + uint32_t alignsize() override; + bool isintegral() override; + bool isfloating() override; + bool isreal() override; + bool isimaginary() override; + bool iscomplex() override; + bool isscalar() override; + bool isunsigned() override; + MATCH implicitConvTo(Type* to) override; + bool isZeroInit(const Loc& loc) override; + TypeBasic* isTypeBasic() override; + void accept(Visitor* v) override; }; -enum class JsonFieldFlags : uint32_t +enum class AliasThisRec { - none = 0u, - compilerInfo = 1u, - buildInfo = 2u, - modules = 4u, - semantics = 8u, + no = 0, + yes = 1, + fwdref = 2, + typeMask = 3, + tracing = 4, + tracingDT = 8, }; -struct Param final -{ - bool obj; - bool multiobj; - bool trace; - bool tracegc; - bool vcg_ast; - DiagnosticReporting useDeprecated; - bool useUnitTests; - bool useInline; - bool release; - bool preservePaths; - DiagnosticReporting warnings; - bool cov; - uint8_t covPercent; - bool ctfe_cov; - bool ignoreUnsupportedPragmas; - bool useModuleInfo; - bool useTypeInfo; - bool useExceptions; - bool useGC; - bool betterC; - bool addMain; - bool allInst; - bool bitfields; - CppStdRevision cplusplus; - Help help; - Verbose v; - FeatureState useDIP25; - FeatureState useDIP1000; - bool ehnogc; - bool useDIP1021; - FeatureState fieldwise; - bool fixAliasThis; - FeatureState rvalueRefParam; - FeatureState noSharedAccess; - bool previewIn; - bool inclusiveInContracts; - bool shortenedMethods; - bool fixImmutableConv; - bool fix16997; - FeatureState dtorFields; - FeatureState systemVariables; - CHECKENABLE useInvariants; - CHECKENABLE useIn; - CHECKENABLE useOut; - CHECKENABLE useArrayBounds; - CHECKENABLE useAssert; - CHECKENABLE useSwitchError; - CHECKENABLE boundscheck; - CHECKACTION checkAction; - _d_dynamicArray< const char > argv0; - Array modFileAliasStrings; - Array* imppath; - Array* fileImppath; - _d_dynamicArray< const char > objdir; - _d_dynamicArray< const char > objname; - _d_dynamicArray< const char > libname; - Output ddoc; - Output dihdr; - Output cxxhdr; - Output json; - JsonFieldFlags jsonFieldFlags; - Output makeDeps; - Output mixinOut; - Output moduleDeps; - uint32_t debuglevel; - uint32_t versionlevel; - bool run; - Array runargs; - Array cppswitches; - const char* cpp; - Array objfiles; - Array linkswitches; - Array linkswitchIsForCC; - Array libfiles; - Array dllfiles; - _d_dynamicArray< const char > deffile; - _d_dynamicArray< const char > resfile; - _d_dynamicArray< const char > exefile; - _d_dynamicArray< const char > mapfile; - bool parsingUnittestsRequired(); - Param() : - obj(true), - multiobj(), - trace(), - tracegc(), - vcg_ast(), - useDeprecated((DiagnosticReporting)1u), - useUnitTests(), - useInline(false), - release(), - preservePaths(), - warnings((DiagnosticReporting)2u), - cov(), - covPercent(), - ctfe_cov(false), - ignoreUnsupportedPragmas(true), - useModuleInfo(true), - useTypeInfo(true), - useExceptions(true), - useGC(true), - betterC(), - addMain(), - allInst(), - bitfields(), - cplusplus((CppStdRevision)201103u), - help(), - v(), - useDIP25((FeatureState)2u), - ehnogc(), - useDIP1021(), - fixAliasThis(), - previewIn(), - inclusiveInContracts(), - shortenedMethods(true), - fixImmutableConv(), - fix16997(true), - useInvariants((CHECKENABLE)0u), - useIn((CHECKENABLE)0u), - useOut((CHECKENABLE)0u), - useArrayBounds((CHECKENABLE)0u), - useAssert((CHECKENABLE)0u), - useSwitchError((CHECKENABLE)0u), - boundscheck((CHECKENABLE)0u), - checkAction((CHECKACTION)0u), - argv0(), - modFileAliasStrings(), - imppath(), - fileImppath(), - objdir(), - objname(), - libname(), - ddoc(), - dihdr(), - cxxhdr(), - json(), - makeDeps(), - mixinOut(), - moduleDeps(), - debuglevel(), - versionlevel(), - run(), - runargs(), - cppswitches(), - cpp(), - objfiles(), - linkswitches(), - linkswitchIsForCC(), - libfiles(), - dllfiles(), - deffile(), - resfile(), - exefile(), - mapfile() - { - } - Param(bool obj, bool multiobj = false, bool trace = false, bool tracegc = false, bool vcg_ast = false, DiagnosticReporting useDeprecated = (DiagnosticReporting)1u, bool useUnitTests = false, bool useInline = false, bool release = false, bool preservePaths = false, DiagnosticReporting warnings = (DiagnosticReporting)2u, bool cov = false, uint8_t covPercent = 0u, bool ctfe_cov = false, bool ignoreUnsupportedPragmas = true, bool useModuleInfo = true, bool useTypeInfo = true, bool useExceptions = true, bool useGC = true, bool betterC = false, bool addMain = false, bool allInst = false, bool bitfields = false, CppStdRevision cplusplus = (CppStdRevision)201103u, Help help = Help(), Verbose v = Verbose(), FeatureState useDIP25 = (FeatureState)2u, FeatureState useDIP1000 = (FeatureState)0u, bool ehnogc = false, bool useDIP1021 = false, FeatureState fieldwise = (FeatureState)0u, bool fixAliasThis = false, FeatureState rvalueRefParam = (FeatureState)0u, FeatureState noSharedAccess = (FeatureState)0u, bool previewIn = false, bool inclusiveInContracts = false, bool shortenedMethods = true, bool fixImmutableConv = false, bool fix16997 = true, FeatureState dtorFields = (FeatureState)0u, FeatureState systemVariables = (FeatureState)0u, CHECKENABLE useInvariants = (CHECKENABLE)0u, CHECKENABLE useIn = (CHECKENABLE)0u, CHECKENABLE useOut = (CHECKENABLE)0u, CHECKENABLE useArrayBounds = (CHECKENABLE)0u, CHECKENABLE useAssert = (CHECKENABLE)0u, CHECKENABLE useSwitchError = (CHECKENABLE)0u, CHECKENABLE boundscheck = (CHECKENABLE)0u, CHECKACTION checkAction = (CHECKACTION)0u, _d_dynamicArray< const char > argv0 = {}, Array modFileAliasStrings = Array(), Array* imppath = nullptr, Array* fileImppath = nullptr, _d_dynamicArray< const char > objdir = {}, _d_dynamicArray< const char > objname = {}, _d_dynamicArray< const char > libname = {}, Output ddoc = Output(), Output dihdr = Output(), Output cxxhdr = Output(), Output json = Output(), JsonFieldFlags jsonFieldFlags = (JsonFieldFlags)0u, Output makeDeps = Output(), Output mixinOut = Output(), Output moduleDeps = Output(), uint32_t debuglevel = 0u, uint32_t versionlevel = 0u, bool run = false, Array runargs = Array(), Array cppswitches = Array(), const char* cpp = nullptr, Array objfiles = Array(), Array linkswitches = Array(), Array linkswitchIsForCC = Array(), Array libfiles = Array(), Array dllfiles = Array(), _d_dynamicArray< const char > deffile = {}, _d_dynamicArray< const char > resfile = {}, _d_dynamicArray< const char > exefile = {}, _d_dynamicArray< const char > mapfile = {}) : - obj(obj), - multiobj(multiobj), - trace(trace), - tracegc(tracegc), - vcg_ast(vcg_ast), - useDeprecated(useDeprecated), - useUnitTests(useUnitTests), - useInline(useInline), - release(release), - preservePaths(preservePaths), - warnings(warnings), - cov(cov), - covPercent(covPercent), - ctfe_cov(ctfe_cov), - ignoreUnsupportedPragmas(ignoreUnsupportedPragmas), - useModuleInfo(useModuleInfo), - useTypeInfo(useTypeInfo), - useExceptions(useExceptions), - useGC(useGC), - betterC(betterC), - addMain(addMain), - allInst(allInst), - bitfields(bitfields), - cplusplus(cplusplus), - help(help), - v(v), - useDIP25(useDIP25), - useDIP1000(useDIP1000), - ehnogc(ehnogc), - useDIP1021(useDIP1021), - fieldwise(fieldwise), - fixAliasThis(fixAliasThis), - rvalueRefParam(rvalueRefParam), - noSharedAccess(noSharedAccess), - previewIn(previewIn), - inclusiveInContracts(inclusiveInContracts), - shortenedMethods(shortenedMethods), - fixImmutableConv(fixImmutableConv), - fix16997(fix16997), - dtorFields(dtorFields), - systemVariables(systemVariables), - useInvariants(useInvariants), - useIn(useIn), - useOut(useOut), - useArrayBounds(useArrayBounds), - useAssert(useAssert), - useSwitchError(useSwitchError), - boundscheck(boundscheck), - checkAction(checkAction), - argv0(argv0), - modFileAliasStrings(modFileAliasStrings), - imppath(imppath), - fileImppath(fileImppath), - objdir(objdir), - objname(objname), - libname(libname), - ddoc(ddoc), - dihdr(dihdr), - cxxhdr(cxxhdr), - json(json), - jsonFieldFlags(jsonFieldFlags), - makeDeps(makeDeps), - mixinOut(mixinOut), - moduleDeps(moduleDeps), - debuglevel(debuglevel), - versionlevel(versionlevel), - run(run), - runargs(runargs), - cppswitches(cppswitches), - cpp(cpp), - objfiles(objfiles), - linkswitches(linkswitches), - linkswitchIsForCC(linkswitchIsForCC), - libfiles(libfiles), - dllfiles(dllfiles), - deffile(deffile), - resfile(resfile), - exefile(exefile), - mapfile(mapfile) - {} -}; - -struct CompileEnv final -{ - uint32_t versionNumber; - _d_dynamicArray< const char > date; - _d_dynamicArray< const char > time; - _d_dynamicArray< const char > vendor; - _d_dynamicArray< const char > timestamp; - bool previewIn; - bool ddocOutput; - bool masm; - CompileEnv() : - versionNumber(), - date(), - time(), - vendor(), - timestamp(), - previewIn(), - ddocOutput(), - masm() - { - } - CompileEnv(uint32_t versionNumber, _d_dynamicArray< const char > date = {}, _d_dynamicArray< const char > time = {}, _d_dynamicArray< const char > vendor = {}, _d_dynamicArray< const char > timestamp = {}, bool previewIn = false, bool ddocOutput = false, bool masm = false) : - versionNumber(versionNumber), - date(date), - time(time), - vendor(vendor), - timestamp(timestamp), - previewIn(previewIn), - ddocOutput(ddocOutput), - masm(masm) - {} -}; - -struct Global final -{ - _d_dynamicArray< const char > inifilename; - _d_dynamicArray< const char > copyright; - _d_dynamicArray< const char > written; - Array* path; - Array* filePath; - char datetime[26LLU]; - CompileEnv compileEnv; - Param params; - uint32_t errors; - uint32_t warnings; - uint32_t gag; - uint32_t gaggedErrors; - uint32_t gaggedWarnings; - void* console; - Array* versionids; - Array* debugids; - bool hasMainFunction; - uint32_t varSequenceNumber; - FileManager* fileManager; - enum : int32_t { recursionLimit = 500 }; - - ErrorSink* errorSink; - ErrorSink* errorSinkNull; - FileName(*preprocess)(FileName , const Loc& , bool& , OutBuffer* ); - uint32_t startGagging(); - bool endGagging(uint32_t oldGagged); - void increaseErrorCount(); - void _init(); - uint32_t versionNumber(); - const char* const versionChars(); - Global() : - inifilename(), - copyright(73, "Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved"), - written(24, "written by Walter Bright"), - path(), - filePath(), - compileEnv(), - params(), - errors(), - warnings(), - gag(), - gaggedErrors(), - gaggedWarnings(), - console(), - versionids(), - debugids(), - hasMainFunction(), - varSequenceNumber(1u), - fileManager(), - errorSink(), - errorSinkNull(), - preprocess() - { - } - Global(_d_dynamicArray< const char > inifilename, _d_dynamicArray< const char > copyright = { 73, "Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved" }, _d_dynamicArray< const char > written = { 24, "written by Walter Bright" }, Array* path = nullptr, Array* filePath = nullptr, CompileEnv compileEnv = CompileEnv(), Param params = Param(), uint32_t errors = 0u, uint32_t warnings = 0u, uint32_t gag = 0u, uint32_t gaggedErrors = 0u, uint32_t gaggedWarnings = 0u, void* console = nullptr, Array* versionids = nullptr, Array* debugids = nullptr, bool hasMainFunction = false, uint32_t varSequenceNumber = 1u, FileManager* fileManager = nullptr, ErrorSink* errorSink = nullptr, ErrorSink* errorSinkNull = nullptr, FileName(*preprocess)(FileName , const Loc& , bool& , OutBuffer* ) = nullptr) : - inifilename(inifilename), - copyright(copyright), - written(written), - path(path), - filePath(filePath), - compileEnv(compileEnv), - params(params), - errors(errors), - warnings(warnings), - gag(gag), - gaggedErrors(gaggedErrors), - gaggedWarnings(gaggedWarnings), - console(console), - versionids(versionids), - debugids(debugids), - hasMainFunction(hasMainFunction), - varSequenceNumber(varSequenceNumber), - fileManager(fileManager), - errorSink(errorSink), - errorSinkNull(errorSinkNull), - preprocess(preprocess) - {} -}; - -extern Global global; - -class Parameter final : public ASTNode -{ -public: - Loc loc; - StorageClass storageClass; - Type* type; - Identifier* ident; - Expression* defaultArg; - UserAttributeDeclaration* userAttribDecl; - static Parameter* create(const Loc& loc, StorageClass storageClass, Type* type, Identifier* ident, Expression* defaultArg, UserAttributeDeclaration* userAttribDecl); - Parameter* syntaxCopy(); - Type* isLazyArray(); - bool isLazy() const; - bool isReference() const; - DYNCAST dyncast() const override; - void accept(Visitor* v) override; - static size_t dim(Array* parameters); - static Parameter* getNth(Array* parameters, size_t nth); - const char* toChars() const override; - bool isCovariant(bool returnByRef, const Parameter* const p, bool previewIn = global.params.previewIn) const; -}; - -enum class RET -{ - regs = 1, - stack = 2, -}; - -enum : uint64_t { SIZE_INVALID = 18446744073709551615LLU }; - -enum class ScopeRef -{ - None = 0, - Scope = 1, - ReturnScope = 2, - Ref = 3, - ReturnRef = 4, - RefScope = 5, - ReturnRef_Scope = 6, - Ref_ReturnScope = 7, - Return = 8, -}; - -enum class TRUSTformat -{ - TRUSTformatDefault = 0, - TRUSTformatSystem = 1, -}; - -class TypeNext : public Type -{ -public: - Type* next; - int32_t hasWild() const final override; - Type* nextOf() final override; - Type* makeConst() final override; - Type* makeImmutable() final override; - Type* makeShared() final override; - Type* makeSharedConst() final override; - Type* makeWild() final override; - Type* makeWildConst() final override; - Type* makeSharedWild() final override; - Type* makeSharedWildConst() final override; - Type* makeMutable() final override; - MATCH constConv(Type* to) override; - uint8_t deduceWild(Type* t, bool isRef) final override; - void transitive(); - void accept(Visitor* v) override; -}; - -class TypeArray : public TypeNext -{ -public: - void accept(Visitor* v) override; -}; - -class TypeAArray final : public TypeArray -{ -public: - Type* index; - Loc loc; - static TypeAArray* create(Type* t, Type* index); - const char* kind() const override; - TypeAArray* syntaxCopy() override; - uinteger_t size(const Loc& loc) override; - bool isZeroInit(const Loc& loc) override; - bool isBoolean() override; - bool hasPointers() override; - MATCH implicitConvTo(Type* to) override; - MATCH constConv(Type* to) override; - void accept(Visitor* v) override; -}; - -class TypeBasic final : public Type -{ -public: - const char* dstring; - uint32_t flags; - const char* kind() const override; - TypeBasic* syntaxCopy() override; - uinteger_t size(const Loc& loc) override; - uint32_t alignsize() override; - bool isintegral() override; - bool isfloating() override; - bool isreal() override; - bool isimaginary() override; - bool iscomplex() override; - bool isscalar() override; - bool isunsigned() override; - MATCH implicitConvTo(Type* to) override; - bool isZeroInit(const Loc& loc) override; - TypeBasic* isTypeBasic() override; - void accept(Visitor* v) override; -}; - -enum class AliasThisRec -{ - no = 0, - yes = 1, - fwdref = 2, - typeMask = 3, - tracing = 4, - tracingDT = 8, -}; - -class TypeClass final : public Type +class TypeClass final : public Type { public: ClassDeclaration* sym; @@ -6042,6 +5509,7 @@ enum class STC : uint64_t lazy_ = 8192LLU, foreach_ = 16384LLU, variadic = 32768LLU, + constscoperef = 65536LLU, templateparameter = 131072LLU, ref_ = 262144LLU, scope_ = 524288LLU, @@ -6079,7 +5547,7 @@ enum class STC : uint64_t register_ = 9007199254740992LLU, volatile_ = 18014398509481984LLU, safeGroup = 962072674304LLU, - IOR = 268288LLU, + IOR = 333824LLU, TYPECTOR = 42983227396LLU, FUNCATTR = 4575000774574080LLU, visibleStorageClasses = 7954966262857631LLU, @@ -6545,6 +6013,15 @@ class Visitor : public ParseTimeVisitor virtual void visit(LoweredAssignExp* e); }; +enum class JsonFieldFlags : uint32_t +{ + none = 0u, + compilerInfo = 1u, + buildInfo = 2u, + modules = 4u, + semantics = 8u, +}; + class StoppableVisitor : public Visitor { public: @@ -6691,6 +6168,78 @@ enum class ErrorKind message = 4, }; +enum class DiagnosticReporting : uint8_t +{ + error = 0u, + inform = 1u, + off = 2u, +}; + +enum class CppStdRevision : uint32_t +{ + cpp98 = 199711u, + cpp11 = 201103u, + cpp14 = 201402u, + cpp17 = 201703u, + cpp20 = 202002u, +}; + +enum class FeatureState : uint8_t +{ + default_ = 0u, + disabled = 1u, + enabled = 2u, +}; + +enum class CHECKENABLE : uint8_t +{ + _default = 0u, + off = 1u, + on = 2u, + safeonly = 3u, +}; + +enum class CHECKACTION : uint8_t +{ + D = 0u, + C = 1u, + halt = 2u, + context = 3u, +}; + +struct CompileEnv final +{ + uint32_t versionNumber; + _d_dynamicArray< const char > date; + _d_dynamicArray< const char > time; + _d_dynamicArray< const char > vendor; + _d_dynamicArray< const char > timestamp; + bool previewIn; + bool ddocOutput; + bool masm; + CompileEnv() : + versionNumber(), + date(), + time(), + vendor(), + timestamp(), + previewIn(), + ddocOutput(), + masm() + { + } + CompileEnv(uint32_t versionNumber, _d_dynamicArray< const char > date = {}, _d_dynamicArray< const char > time = {}, _d_dynamicArray< const char > vendor = {}, _d_dynamicArray< const char > timestamp = {}, bool previewIn = false, bool ddocOutput = false, bool masm = false) : + versionNumber(versionNumber), + date(date), + time(time), + vendor(vendor), + timestamp(timestamp), + previewIn(previewIn), + ddocOutput(ddocOutput), + masm(masm) + {} +}; + typedef _d_real longdouble; typedef uint64_t uint64_t; @@ -7904,533 +7453,986 @@ class WithScopeSymbol final : public ScopeDsymbol void accept(Visitor* v) override; }; -class ArrayScopeSymbol final : public ScopeDsymbol +class ArrayScopeSymbol final : public ScopeDsymbol +{ +public: + RootObject* arrayContent; + ArrayScopeSymbol* isArrayScopeSymbol() override; + void accept(Visitor* v) override; +}; + +class OverloadSet final : public Dsymbol +{ +public: + Array a; + void push(Dsymbol* s); + OverloadSet* isOverloadSet() override; + const char* kind() const override; + void accept(Visitor* v) override; +}; + +class ForwardingScopeDsymbol final : public ScopeDsymbol +{ +public: + Dsymbol* symtabInsert(Dsymbol* s) override; + Dsymbol* symtabLookup(Dsymbol* s, Identifier* id) override; + void importScope(Dsymbol* s, Visibility visibility) override; + const char* kind() const override; + ForwardingScopeDsymbol* isForwardingScopeDsymbol() override; +}; + +class ExpressionDsymbol final : public Dsymbol +{ +public: + Expression* exp; + ExpressionDsymbol(Expression* exp); + ExpressionDsymbol* isExpressionDsymbol() override; +}; + +class AliasAssign final : public Dsymbol +{ +public: + Identifier* ident; + Type* type; + Dsymbol* aliassym; + AliasAssign* syntaxCopy(Dsymbol* s) override; + AliasAssign* isAliasAssign() override; + const char* kind() const override; + void accept(Visitor* v) override; +}; + +class DsymbolTable final : public RootObject +{ +public: + AssocArray tab; + Dsymbol* lookup(const Identifier* const ident); + void update(Dsymbol* s); + Dsymbol* insert(Dsymbol* s); + Dsymbol* insert(const Identifier* const ident, Dsymbol* s); + size_t length() const; + DsymbolTable(); +}; + +extern void dsymbolSemantic(Dsymbol* dsym, Scope* sc); + +extern void addMember(Dsymbol* dsym, Scope* sc, ScopeDsymbol* sds); + +extern Dsymbol* search(Dsymbol* d, const Loc& loc, Identifier* ident, uint32_t flags = 0u); + +extern void setScope(Dsymbol* d, Scope* sc); + +extern void importAll(Dsymbol* d, Scope* sc); + +class ImportAllVisitor : public Visitor +{ +public: + using Visitor::visit; + Scope* sc; + ImportAllVisitor(Scope* sc); + void visit(Dsymbol* d) override; + void visit(Import* imp) override; + void visit(Module* m) override; + void visit(AttribDeclaration* atb) override; + void visit(StaticIfDeclaration* _) override; + void visit(StaticForeachDeclaration* _) override; +}; + +extern void setFieldOffset(Dsymbol* d, AggregateDeclaration* ad, FieldState* fieldState, bool isunion); + +extern void genCppHdrFiles(Array& ms); + +extern Expression* resolveProperties(Scope* sc, Expression* e); + +extern Expression* expressionSemantic(Expression* e, Scope* sc); + +extern Expression* toLvalue(Expression* _this, Scope* sc, const char* action); + +extern Expression* modifiableLvalue(Expression* _this, Scope* sc); + +extern const char* toChars(const Expression* const e); + +extern const char* toChars(const Initializer* const i); + +extern const char* toChars(const Type* const t); + +extern void json_generate(Array& modules, OutBuffer& buf); + +extern JsonFieldFlags tryParseJsonField(const char* fieldName); + +class NOGCVisitor final : public StoppableVisitor +{ +public: + using StoppableVisitor::visit; + FuncDeclaration* f; + bool checkOnly; + bool err; + void doCond(Expression* exp); + void visit(Expression* e) override; + void visit(DeclarationExp* e) override; + void visit(CallExp* e) override; + void visit(ArrayLiteralExp* e) override; + void visit(AssocArrayLiteralExp* e) override; + void visit(NewExp* e) override; + void visit(DeleteExp* e) override; + void visit(IndexExp* e) override; + void visit(AssignExp* e) override; + void visit(CatAssignExp* e) override; + void visit(CatExp* e) override; +}; + +class Objc { public: - RootObject* arrayContent; - ArrayScopeSymbol* isArrayScopeSymbol() override; - void accept(Visitor* v) override; + static void _init(); + static void deinitialize(); + virtual void setObjc(ClassDeclaration* cd) = 0; + virtual void setObjc(InterfaceDeclaration* ) = 0; + virtual const char* toPrettyChars(ClassDeclaration* classDeclaration, bool qualifyTypes) const = 0; + virtual void setSelector(FuncDeclaration* , Scope* sc) = 0; + virtual void validateSelector(FuncDeclaration* fd) = 0; + virtual void checkLinkage(FuncDeclaration* fd) = 0; + virtual bool isVirtual(const FuncDeclaration* const fd) const = 0; + virtual void setAsOptional(FuncDeclaration* functionDeclaration, Scope* sc) const = 0; + virtual void validateOptional(FuncDeclaration* functionDeclaration) const = 0; + virtual ClassDeclaration* getParent(FuncDeclaration* fd, ClassDeclaration* cd) const = 0; + virtual void addToClassMethodList(FuncDeclaration* fd, ClassDeclaration* cd) const = 0; + virtual AggregateDeclaration* isThis(FuncDeclaration* funcDeclaration) const = 0; + virtual VarDeclaration* createSelectorParameter(FuncDeclaration* fd, Scope* sc) const = 0; + virtual void setMetaclass(InterfaceDeclaration* interfaceDeclaration, Scope* sc) const = 0; + virtual void setMetaclass(ClassDeclaration* classDeclaration, Scope* sc) const = 0; + virtual ClassDeclaration* getRuntimeMetaclass(ClassDeclaration* classDeclaration) const = 0; + virtual void addSymbols(AttribDeclaration* attribDeclaration, Array* classes, Array* categories) const = 0; + virtual void addSymbols(ClassDeclaration* classDeclaration, Array* classes, Array* categories) const = 0; + virtual void checkOffsetof(Expression* expression, AggregateDeclaration* aggregateDeclaration) const = 0; + virtual void checkTupleof(Expression* expression, TypeClass* type) const = 0; }; -class OverloadSet final : public Dsymbol +template +class PermissiveVisitor : public ParseTimeVisitor { public: - Array a; - void push(Dsymbol* s); - OverloadSet* isOverloadSet() override; - const char* kind() const override; - void accept(Visitor* v) override; + typedef ParseTimeVisitor visit; + virtual void visit(typename AST::Dsymbol ) override; + virtual void visit(typename AST::Parameter ) override; + virtual void visit(typename AST::Statement ) override; + virtual void visit(typename AST::Type ) override; + virtual void visit(typename AST::Expression ) override; + virtual void visit(typename AST::TemplateParameter ) override; + virtual void visit(typename AST::Condition ) override; + virtual void visit(typename AST::Initializer ) override; }; -class ForwardingScopeDsymbol final : public ScopeDsymbol +extern void semantic2(Dsymbol* dsym, Scope* sc); + +extern void semantic3(Dsymbol* dsym, Scope* sc); + +extern void semanticTypeInfoMembers(StructDeclaration* sd); + +extern Statement* statementSemantic(Statement* s, Scope* sc); + +struct Target final { + enum class OS : uint8_t + { + none = 0u, + linux = 1u, + Windows = 2u, + OSX = 4u, + OpenBSD = 8u, + FreeBSD = 16u, + Solaris = 32u, + DragonFlyBSD = 64u, + all = 127u, + Posix = 125u, + }; + + OS os; + uint8_t osMajor; + uint8_t ptrsize; + uint8_t realsize; + uint8_t realpad; + uint8_t realalignsize; + uint8_t classinfosize; + uint64_t maxStaticDataSize; + TargetC c; + TargetCPP cpp; + TargetObjC objc; + _d_dynamicArray< const char > architectureName; + CPU cpu; + bool isX86_64; + bool isLP64; + _d_dynamicArray< const char > obj_ext; + _d_dynamicArray< const char > lib_ext; + _d_dynamicArray< const char > dll_ext; + bool run_noext; + bool omfobj; + template + struct FPTypeProperties final + { + real_t max; + real_t min_normal; + real_t nan; + real_t infinity; + real_t epsilon; + int64_t dig; + int64_t mant_dig; + int64_t max_exp; + int64_t min_exp; + int64_t max_10_exp; + int64_t min_10_exp; + FPTypeProperties() + { + } + }; + + FPTypeProperties FloatProperties; + FPTypeProperties DoubleProperties; + FPTypeProperties<_d_real > RealProperties; +private: + Type* tvalist; + const Param* params; public: - Dsymbol* symtabInsert(Dsymbol* s) override; - Dsymbol* symtabLookup(Dsymbol* s, Identifier* id) override; - void importScope(Dsymbol* s, Visibility visibility) override; - const char* kind() const override; - ForwardingScopeDsymbol* isForwardingScopeDsymbol() override; -}; + void _init(const Param& params); + void setCPU(); + void deinitialize(); + uint32_t alignsize(Type* type); + uint32_t fieldalign(Type* type); + Type* va_listType(const Loc& loc, Scope* sc); + int32_t isVectorTypeSupported(int32_t sz, Type* type); + bool isVectorOpSupported(Type* type, EXP op, Type* t2 = nullptr); + LINK systemLinkage(); + TypeTuple* toArgTypes(Type* t); + bool isReturnOnStack(TypeFunction* tf, bool needsThis); + bool preferPassByRef(Type* t); +private: + enum class TargetInfoKeys + { + cppRuntimeLibrary = 0, + cppStd = 1, + floatAbi = 2, + objectFormat = 3, + CET = 4, + }; -class ExpressionDsymbol final : public Dsymbol -{ public: - Expression* exp; - ExpressionDsymbol(Expression* exp); - ExpressionDsymbol* isExpressionDsymbol() override; + Expression* getTargetInfo(const char* name, const Loc& loc); + bool isCalleeDestroyingArgs(TypeFunction* tf); + bool libraryObjectMonitors(FuncDeclaration* fd, Statement* fbody); + bool supportsLinkerDirective() const; + Target() : + os((OS)1u), + osMajor(0u), + ptrsize(), + realsize(), + realpad(), + realalignsize(), + classinfosize(), + maxStaticDataSize(), + c(), + cpp(), + objc(), + architectureName(), + cpu((CPU)11u), + isX86_64(true), + isLP64(), + obj_ext(), + lib_ext(), + dll_ext(), + run_noext(), + omfobj(false), + FloatProperties(), + DoubleProperties(), + RealProperties(), + tvalist(), + params() + { + } + Target(OS os, uint8_t osMajor = 0u, uint8_t ptrsize = 0u, uint8_t realsize = 0u, uint8_t realpad = 0u, uint8_t realalignsize = 0u, uint8_t classinfosize = 0u, uint64_t maxStaticDataSize = 0LLU, TargetC c = TargetC(), TargetCPP cpp = TargetCPP(), TargetObjC objc = TargetObjC(), _d_dynamicArray< const char > architectureName = {}, CPU cpu = (CPU)11u, bool isX86_64 = true, bool isLP64 = false, _d_dynamicArray< const char > obj_ext = {}, _d_dynamicArray< const char > lib_ext = {}, _d_dynamicArray< const char > dll_ext = {}, bool run_noext = false, bool omfobj = false, FPTypeProperties FloatProperties = FPTypeProperties(), FPTypeProperties DoubleProperties = FPTypeProperties(), FPTypeProperties<_d_real > RealProperties = FPTypeProperties<_d_real >(), Type* tvalist = nullptr, const Param* params = nullptr) : + os(os), + osMajor(osMajor), + ptrsize(ptrsize), + realsize(realsize), + realpad(realpad), + realalignsize(realalignsize), + classinfosize(classinfosize), + maxStaticDataSize(maxStaticDataSize), + c(c), + cpp(cpp), + objc(objc), + architectureName(architectureName), + cpu(cpu), + isX86_64(isX86_64), + isLP64(isLP64), + obj_ext(obj_ext), + lib_ext(lib_ext), + dll_ext(dll_ext), + run_noext(run_noext), + omfobj(omfobj), + FloatProperties(FloatProperties), + DoubleProperties(DoubleProperties), + RealProperties(RealProperties), + tvalist(tvalist), + params(params) + {} }; -class AliasAssign final : public Dsymbol +extern Target target; + +extern bool tpsemantic(TemplateParameter* tp, Scope* sc, Array* parameters); + +extern bool genTypeInfo(Expression* e, const Loc& loc, Type* torig, Scope* sc); + +extern Type* getTypeInfoType(const Loc& loc, Type* t, Scope* sc, bool genObjCode = true); + +extern bool isSpeculativeType(Type* t); + +extern bool builtinTypeInfo(Type* t); + +class SemanticTimeTransitiveVisitor : public SemanticTimePermissiveVisitor { public: - Identifier* ident; - Type* type; - Dsymbol* aliassym; - AliasAssign* syntaxCopy(Dsymbol* s) override; - AliasAssign* isAliasAssign() override; - const char* kind() const override; - void accept(Visitor* v) override; + using SemanticTimePermissiveVisitor::visit; + void visit(ExpStatement* s) override; + void visit(MixinStatement* s) override; + void visit(CompoundStatement* s) override; + virtual void visitVarDecl(VarDeclaration* v); + void visit(CompoundDeclarationStatement* s) override; + void visit(ScopeStatement* s) override; + void visit(WhileStatement* s) override; + void visit(DoStatement* s) override; + void visit(ForStatement* s) override; + void visit(ForeachStatement* s) override; + void visit(ForeachRangeStatement* s) override; + void visit(StaticForeachStatement* s) override; + void visit(IfStatement* s) override; + void visit(ConditionalStatement* s) override; + void visit(PragmaStatement* s) override; + void visit(StaticAssertStatement* s) override; + void visit(SwitchStatement* s) override; + void visit(CaseStatement* s) override; + void visit(CaseRangeStatement* s) override; + void visit(DefaultStatement* s) override; + void visit(GotoCaseStatement* s) override; + void visit(ReturnStatement* s) override; + void visit(SynchronizedStatement* s) override; + void visit(WithStatement* s) override; + void visit(TryCatchStatement* s) override; + void visit(TryFinallyStatement* s) override; + void visit(ScopeGuardStatement* s) override; + void visit(ThrowStatement* s) override; + void visit(LabelStatement* s) override; + void visit(ImportStatement* s) override; + virtual void visit(Catch* c); + virtual void visitType(Type* t); + virtual void visitFunctionType(TypeFunction* t, TemplateDeclaration* td); + void visit(TypeVector* t) override; + void visit(TypeSArray* t) override; + void visit(TypeDArray* t) override; + void visit(TypeAArray* t) override; + void visit(TypePointer* t) override; + void visit(TypeReference* t) override; + void visit(TypeFunction* t) override; + void visit(TypeDelegate* t) override; + virtual void visitTypeQualified(TypeQualified* t); + void visit(TypeIdentifier* t) override; + void visit(TypeInstance* t) override; + void visit(TypeTypeof* t) override; + void visit(TypeReturn* t) override; + void visit(TypeTuple* t) override; + void visit(TypeSlice* t) override; + void visit(TypeTraits* t) override; + void visit(TypeMixin* t) override; + void visit(StaticAssert* s) override; + void visit(EnumMember* em) override; + virtual void visitAttribDeclaration(AttribDeclaration* d); + void visit(AttribDeclaration* d) override; + void visit(StorageClassDeclaration* d) override; + void visit(DeprecatedDeclaration* d) override; + void visit(LinkDeclaration* d) override; + void visit(CPPMangleDeclaration* d) override; + void visit(VisibilityDeclaration* d) override; + void visit(AlignDeclaration* d) override; + void visit(AnonDeclaration* d) override; + void visit(PragmaDeclaration* d) override; + void visit(ConditionalDeclaration* d) override; + void visit(MixinDeclaration* d) override; + void visit(UserAttributeDeclaration* d) override; + virtual void visitFuncBody(FuncDeclaration* f); + virtual void visitBaseClasses(ClassDeclaration* d); + virtual bool visitEponymousMember(TemplateDeclaration* d); + virtual void visitTemplateParameters(Array* parameters); + void visit(TemplateDeclaration* d) override; + virtual void visitObject(RootObject* oarg); + virtual void visitTiargs(TemplateInstance* ti); + void visit(TemplateInstance* ti) override; + void visit(TemplateMixin* tm) override; + void visit(EnumDeclaration* d) override; + void visit(Nspace* d) override; + void visit(StructDeclaration* d) override; + void visit(UnionDeclaration* d) override; + void visit(ClassDeclaration* d) override; + void visit(InterfaceDeclaration* d) override; + void visit(AliasDeclaration* d) override; + void visit(AliasAssign* d) override; + void visit(VarDeclaration* d) override; + void visit(FuncDeclaration* f) override; + void visit(FuncLiteralDeclaration* f) override; + void visit(PostBlitDeclaration* d) override; + void visit(DtorDeclaration* d) override; + void visit(CtorDeclaration* d) override; + void visit(StaticCtorDeclaration* d) override; + void visit(StaticDtorDeclaration* d) override; + void visit(InvariantDeclaration* d) override; + void visit(UnitTestDeclaration* d) override; + void visit(NewDeclaration* d) override; + void visit(StructInitializer* si) override; + void visit(ArrayInitializer* ai) override; + void visit(ExpInitializer* ei) override; + void visit(CInitializer* ci) override; + void visit(ArrayLiteralExp* e) override; + void visit(AssocArrayLiteralExp* e) override; + void visit(TypeExp* e) override; + void visit(ScopeExp* e) override; + void visit(NewExp* e) override; + void visit(NewAnonClassExp* e) override; + void visit(TupleExp* e) override; + void visit(FuncExp* e) override; + void visit(DeclarationExp* e) override; + void visit(TypeidExp* e) override; + void visit(TraitsExp* e) override; + void visit(IsExp* e) override; + void visit(UnaExp* e) override; + void visit(BinExp* e) override; + void visit(MixinExp* e) override; + void visit(ImportExp* e) override; + void visit(AssertExp* e) override; + void visit(DotIdExp* e) override; + void visit(DotTemplateInstanceExp* e) override; + void visit(CallExp* e) override; + void visit(PtrExp* e) override; + void visit(DeleteExp* e) override; + void visit(CastExp* e) override; + void visit(IntervalExp* e) override; + void visit(ArrayExp* e) override; + void visit(PostExp* e) override; + void visit(CondExp* e) override; + void visit(GenericExp* e) override; + void visit(ThrowExp* e) override; + void visit(TemplateTypeParameter* tp) override; + void visit(TemplateThisParameter* tp) override; + void visit(TemplateAliasParameter* tp) override; + void visit(TemplateValueParameter* tp) override; + void visit(StaticIfCondition* c) override; + void visit(Parameter* p) override; + void visit(Module* m) override; + void visit(PeelStatement* s) override; + void visit(UnrolledLoopStatement* s) override; + void visit(DebugStatement* s) override; + void visit(ForwardingStatement* s) override; + void visit(StructLiteralExp* e) override; + void visit(CompoundLiteralExp* e) override; + void visit(DotTemplateExp* e) override; + void visit(DotVarExp* e) override; + void visit(DelegateExp* e) override; + void visit(DotTypeExp* e) override; + void visit(VectorExp* e) override; + void visit(VectorArrayExp* e) override; + void visit(SliceExp* e) override; + void visit(ArrayLengthExp* e) override; + void visit(DelegatePtrExp* e) override; + void visit(DelegateFuncptrExp* e) override; + void visit(DotExp* e) override; + void visit(IndexExp* e) override; + void visit(RemoveExp* e) override; + void visit(LoweredAssignExp* e) override; }; -class DsymbolTable final : public RootObject -{ -public: - AssocArray tab; - Dsymbol* lookup(const Identifier* const ident); - void update(Dsymbol* s); - Dsymbol* insert(Dsymbol* s); - Dsymbol* insert(const Identifier* const ident, Dsymbol* s); - size_t length() const; - DsymbolTable(); -}; +extern _d_real creall(complex_t x); -extern void dsymbolSemantic(Dsymbol* dsym, Scope* sc); +extern _d_real cimagl(complex_t x); -extern void addMember(Dsymbol* dsym, Scope* sc, ScopeDsymbol* sds); +extern void browse(const char* url); -extern Dsymbol* search(Dsymbol* d, const Loc& loc, Identifier* ident, uint32_t flags = 0u); +extern void error(const Loc& loc, const char* format, ...); -extern void setScope(Dsymbol* d, Scope* sc); +extern void error(const char* filename, uint32_t linnum, uint32_t charnum, const char* format, ...); -extern void importAll(Dsymbol* d, Scope* sc); +extern void errorSupplemental(const Loc& loc, const char* format, ...); -class ImportAllVisitor : public Visitor -{ -public: - using Visitor::visit; - Scope* sc; - ImportAllVisitor(Scope* sc); - void visit(Dsymbol* d) override; - void visit(Import* imp) override; - void visit(Module* m) override; - void visit(AttribDeclaration* atb) override; - void visit(StaticIfDeclaration* _) override; - void visit(StaticForeachDeclaration* _) override; -}; +extern void warning(const Loc& loc, const char* format, ...); -extern void setFieldOffset(Dsymbol* d, AggregateDeclaration* ad, FieldState* fieldState, bool isunion); +extern void warningSupplemental(const Loc& loc, const char* format, ...); -extern void genCppHdrFiles(Array& ms); +extern void deprecation(const Loc& loc, const char* format, ...); -extern Expression* resolveProperties(Scope* sc, Expression* e); +extern void deprecationSupplemental(const Loc& loc, const char* format, ...); -extern Expression* expressionSemantic(Expression* e, Scope* sc); +extern void message(const Loc& loc, const char* format, ...); -extern Expression* toLvalue(Expression* _this, Scope* sc, const char* action); +extern void message(const char* format, ...); -extern Expression* modifiableLvalue(Expression* _this, Scope* sc); +extern void tip(const char* format, ...); -extern const char* toChars(const Expression* const e); +extern void verrorReport(const Loc& loc, const char* format, va_list ap, ErrorKind kind, const char* p1 = nullptr, const char* p2 = nullptr); -extern const char* toChars(const Initializer* const i); +extern void verrorReportSupplemental(const Loc& loc, const char* format, va_list ap, ErrorKind kind); -extern const char* toChars(const Type* const t); +extern void fatal(); -extern void json_generate(Array& modules, OutBuffer& buf); +extern void halt(); -extern JsonFieldFlags tryParseJsonField(const char* fieldName); +struct Output final +{ + bool doOutput; + bool fullOutput; + _d_dynamicArray< const char > dir; + _d_dynamicArray< const char > name; + Array files; + OutBuffer* buffer; + int32_t bufferLines; + Output() : + doOutput(), + fullOutput(), + dir(), + name(), + files(), + buffer(), + bufferLines() + { + } + Output(bool doOutput, bool fullOutput = false, _d_dynamicArray< const char > dir = {}, _d_dynamicArray< const char > name = {}, Array files = Array(), OutBuffer* buffer = nullptr, int32_t bufferLines = 0) : + doOutput(doOutput), + fullOutput(fullOutput), + dir(dir), + name(name), + files(files), + buffer(buffer), + bufferLines(bufferLines) + {} +}; -class NOGCVisitor final : public StoppableVisitor +struct Help final { -public: - using StoppableVisitor::visit; - FuncDeclaration* f; - bool checkOnly; - bool err; - void doCond(Expression* exp); - void visit(Expression* e) override; - void visit(DeclarationExp* e) override; - void visit(CallExp* e) override; - void visit(ArrayLiteralExp* e) override; - void visit(AssocArrayLiteralExp* e) override; - void visit(NewExp* e) override; - void visit(DeleteExp* e) override; - void visit(IndexExp* e) override; - void visit(AssignExp* e) override; - void visit(CatAssignExp* e) override; - void visit(CatExp* e) override; + bool manual; + bool usage; + bool mcpu; + bool transition; + bool check; + bool checkAction; + bool revert; + bool preview; + bool externStd; + bool hc; + Help() : + manual(), + usage(), + mcpu(), + transition(), + check(), + checkAction(), + revert(), + preview(), + externStd(), + hc() + { + } + Help(bool manual, bool usage = false, bool mcpu = false, bool transition = false, bool check = false, bool checkAction = false, bool revert = false, bool preview = false, bool externStd = false, bool hc = false) : + manual(manual), + usage(usage), + mcpu(mcpu), + transition(transition), + check(check), + checkAction(checkAction), + revert(revert), + preview(preview), + externStd(externStd), + hc(hc) + {} }; -class Objc +struct Verbose final { -public: - static void _init(); - static void deinitialize(); - virtual void setObjc(ClassDeclaration* cd) = 0; - virtual void setObjc(InterfaceDeclaration* ) = 0; - virtual const char* toPrettyChars(ClassDeclaration* classDeclaration, bool qualifyTypes) const = 0; - virtual void setSelector(FuncDeclaration* , Scope* sc) = 0; - virtual void validateSelector(FuncDeclaration* fd) = 0; - virtual void checkLinkage(FuncDeclaration* fd) = 0; - virtual bool isVirtual(const FuncDeclaration* const fd) const = 0; - virtual void setAsOptional(FuncDeclaration* functionDeclaration, Scope* sc) const = 0; - virtual void validateOptional(FuncDeclaration* functionDeclaration) const = 0; - virtual ClassDeclaration* getParent(FuncDeclaration* fd, ClassDeclaration* cd) const = 0; - virtual void addToClassMethodList(FuncDeclaration* fd, ClassDeclaration* cd) const = 0; - virtual AggregateDeclaration* isThis(FuncDeclaration* funcDeclaration) const = 0; - virtual VarDeclaration* createSelectorParameter(FuncDeclaration* fd, Scope* sc) const = 0; - virtual void setMetaclass(InterfaceDeclaration* interfaceDeclaration, Scope* sc) const = 0; - virtual void setMetaclass(ClassDeclaration* classDeclaration, Scope* sc) const = 0; - virtual ClassDeclaration* getRuntimeMetaclass(ClassDeclaration* classDeclaration) const = 0; - virtual void addSymbols(AttribDeclaration* attribDeclaration, Array* classes, Array* categories) const = 0; - virtual void addSymbols(ClassDeclaration* classDeclaration, Array* classes, Array* categories) const = 0; - virtual void checkOffsetof(Expression* expression, AggregateDeclaration* aggregateDeclaration) const = 0; - virtual void checkTupleof(Expression* expression, TypeClass* type) const = 0; + bool verbose; + bool showColumns; + bool tls; + bool templates; + bool templatesListInstances; + bool gc; + bool field; + bool complex; + bool vin; + bool showGaggedErrors; + bool printErrorContext; + bool logo; + bool color; + bool cov; + MessageStyle messageStyle; + uint32_t errorLimit; + uint32_t errorSupplementLimit; + uint32_t errorSupplementCount(); + Verbose() : + verbose(), + showColumns(), + tls(), + templates(), + templatesListInstances(), + gc(), + field(), + complex(true), + vin(), + showGaggedErrors(), + printErrorContext(), + logo(), + color(), + cov(), + messageStyle((MessageStyle)0u), + errorLimit(20u), + errorSupplementLimit(6u) + { + } + Verbose(bool verbose, bool showColumns = false, bool tls = false, bool templates = false, bool templatesListInstances = false, bool gc = false, bool field = false, bool complex = true, bool vin = false, bool showGaggedErrors = false, bool printErrorContext = false, bool logo = false, bool color = false, bool cov = false, MessageStyle messageStyle = (MessageStyle)0u, uint32_t errorLimit = 20u, uint32_t errorSupplementLimit = 6u) : + verbose(verbose), + showColumns(showColumns), + tls(tls), + templates(templates), + templatesListInstances(templatesListInstances), + gc(gc), + field(field), + complex(complex), + vin(vin), + showGaggedErrors(showGaggedErrors), + printErrorContext(printErrorContext), + logo(logo), + color(color), + cov(cov), + messageStyle(messageStyle), + errorLimit(errorLimit), + errorSupplementLimit(errorSupplementLimit) + {} }; -template -class PermissiveVisitor : public ParseTimeVisitor +struct Param final { -public: - typedef ParseTimeVisitor visit; - virtual void visit(typename AST::Dsymbol ) override; - virtual void visit(typename AST::Parameter ) override; - virtual void visit(typename AST::Statement ) override; - virtual void visit(typename AST::Type ) override; - virtual void visit(typename AST::Expression ) override; - virtual void visit(typename AST::TemplateParameter ) override; - virtual void visit(typename AST::Condition ) override; - virtual void visit(typename AST::Initializer ) override; + bool obj; + bool multiobj; + bool trace; + bool tracegc; + bool vcg_ast; + DiagnosticReporting useDeprecated; + bool useUnitTests; + bool useInline; + bool release; + bool preservePaths; + DiagnosticReporting warnings; + bool cov; + uint8_t covPercent; + bool ctfe_cov; + bool ignoreUnsupportedPragmas; + bool useModuleInfo; + bool useTypeInfo; + bool useExceptions; + bool useGC; + bool betterC; + bool addMain; + bool allInst; + bool bitfields; + CppStdRevision cplusplus; + Help help; + Verbose v; + FeatureState useDIP25; + FeatureState useDIP1000; + bool ehnogc; + bool useDIP1021; + FeatureState fieldwise; + bool fixAliasThis; + FeatureState rvalueRefParam; + FeatureState noSharedAccess; + bool previewIn; + bool inclusiveInContracts; + bool shortenedMethods; + bool fixImmutableConv; + bool fix16997; + FeatureState dtorFields; + FeatureState systemVariables; + CHECKENABLE useInvariants; + CHECKENABLE useIn; + CHECKENABLE useOut; + CHECKENABLE useArrayBounds; + CHECKENABLE useAssert; + CHECKENABLE useSwitchError; + CHECKENABLE boundscheck; + CHECKACTION checkAction; + _d_dynamicArray< const char > argv0; + Array modFileAliasStrings; + Array* imppath; + Array* fileImppath; + _d_dynamicArray< const char > objdir; + _d_dynamicArray< const char > objname; + _d_dynamicArray< const char > libname; + Output ddoc; + Output dihdr; + Output cxxhdr; + Output json; + JsonFieldFlags jsonFieldFlags; + Output makeDeps; + Output mixinOut; + Output moduleDeps; + uint32_t debuglevel; + uint32_t versionlevel; + bool run; + Array runargs; + Array cppswitches; + const char* cpp; + Array objfiles; + Array linkswitches; + Array linkswitchIsForCC; + Array libfiles; + Array dllfiles; + _d_dynamicArray< const char > deffile; + _d_dynamicArray< const char > resfile; + _d_dynamicArray< const char > exefile; + _d_dynamicArray< const char > mapfile; + bool parsingUnittestsRequired(); + Param() : + obj(true), + multiobj(), + trace(), + tracegc(), + vcg_ast(), + useDeprecated((DiagnosticReporting)1u), + useUnitTests(), + useInline(false), + release(), + preservePaths(), + warnings((DiagnosticReporting)2u), + cov(), + covPercent(), + ctfe_cov(false), + ignoreUnsupportedPragmas(true), + useModuleInfo(true), + useTypeInfo(true), + useExceptions(true), + useGC(true), + betterC(), + addMain(), + allInst(), + bitfields(), + cplusplus((CppStdRevision)201103u), + help(), + v(), + useDIP25((FeatureState)2u), + ehnogc(), + useDIP1021(), + fixAliasThis(), + previewIn(), + inclusiveInContracts(), + shortenedMethods(true), + fixImmutableConv(), + fix16997(true), + useInvariants((CHECKENABLE)0u), + useIn((CHECKENABLE)0u), + useOut((CHECKENABLE)0u), + useArrayBounds((CHECKENABLE)0u), + useAssert((CHECKENABLE)0u), + useSwitchError((CHECKENABLE)0u), + boundscheck((CHECKENABLE)0u), + checkAction((CHECKACTION)0u), + argv0(), + modFileAliasStrings(), + imppath(), + fileImppath(), + objdir(), + objname(), + libname(), + ddoc(), + dihdr(), + cxxhdr(), + json(), + makeDeps(), + mixinOut(), + moduleDeps(), + debuglevel(), + versionlevel(), + run(), + runargs(), + cppswitches(), + cpp(), + objfiles(), + linkswitches(), + linkswitchIsForCC(), + libfiles(), + dllfiles(), + deffile(), + resfile(), + exefile(), + mapfile() + { + } + Param(bool obj, bool multiobj = false, bool trace = false, bool tracegc = false, bool vcg_ast = false, DiagnosticReporting useDeprecated = (DiagnosticReporting)1u, bool useUnitTests = false, bool useInline = false, bool release = false, bool preservePaths = false, DiagnosticReporting warnings = (DiagnosticReporting)2u, bool cov = false, uint8_t covPercent = 0u, bool ctfe_cov = false, bool ignoreUnsupportedPragmas = true, bool useModuleInfo = true, bool useTypeInfo = true, bool useExceptions = true, bool useGC = true, bool betterC = false, bool addMain = false, bool allInst = false, bool bitfields = false, CppStdRevision cplusplus = (CppStdRevision)201103u, Help help = Help(), Verbose v = Verbose(), FeatureState useDIP25 = (FeatureState)2u, FeatureState useDIP1000 = (FeatureState)0u, bool ehnogc = false, bool useDIP1021 = false, FeatureState fieldwise = (FeatureState)0u, bool fixAliasThis = false, FeatureState rvalueRefParam = (FeatureState)0u, FeatureState noSharedAccess = (FeatureState)0u, bool previewIn = false, bool inclusiveInContracts = false, bool shortenedMethods = true, bool fixImmutableConv = false, bool fix16997 = true, FeatureState dtorFields = (FeatureState)0u, FeatureState systemVariables = (FeatureState)0u, CHECKENABLE useInvariants = (CHECKENABLE)0u, CHECKENABLE useIn = (CHECKENABLE)0u, CHECKENABLE useOut = (CHECKENABLE)0u, CHECKENABLE useArrayBounds = (CHECKENABLE)0u, CHECKENABLE useAssert = (CHECKENABLE)0u, CHECKENABLE useSwitchError = (CHECKENABLE)0u, CHECKENABLE boundscheck = (CHECKENABLE)0u, CHECKACTION checkAction = (CHECKACTION)0u, _d_dynamicArray< const char > argv0 = {}, Array modFileAliasStrings = Array(), Array* imppath = nullptr, Array* fileImppath = nullptr, _d_dynamicArray< const char > objdir = {}, _d_dynamicArray< const char > objname = {}, _d_dynamicArray< const char > libname = {}, Output ddoc = Output(), Output dihdr = Output(), Output cxxhdr = Output(), Output json = Output(), JsonFieldFlags jsonFieldFlags = (JsonFieldFlags)0u, Output makeDeps = Output(), Output mixinOut = Output(), Output moduleDeps = Output(), uint32_t debuglevel = 0u, uint32_t versionlevel = 0u, bool run = false, Array runargs = Array(), Array cppswitches = Array(), const char* cpp = nullptr, Array objfiles = Array(), Array linkswitches = Array(), Array linkswitchIsForCC = Array(), Array libfiles = Array(), Array dllfiles = Array(), _d_dynamicArray< const char > deffile = {}, _d_dynamicArray< const char > resfile = {}, _d_dynamicArray< const char > exefile = {}, _d_dynamicArray< const char > mapfile = {}) : + obj(obj), + multiobj(multiobj), + trace(trace), + tracegc(tracegc), + vcg_ast(vcg_ast), + useDeprecated(useDeprecated), + useUnitTests(useUnitTests), + useInline(useInline), + release(release), + preservePaths(preservePaths), + warnings(warnings), + cov(cov), + covPercent(covPercent), + ctfe_cov(ctfe_cov), + ignoreUnsupportedPragmas(ignoreUnsupportedPragmas), + useModuleInfo(useModuleInfo), + useTypeInfo(useTypeInfo), + useExceptions(useExceptions), + useGC(useGC), + betterC(betterC), + addMain(addMain), + allInst(allInst), + bitfields(bitfields), + cplusplus(cplusplus), + help(help), + v(v), + useDIP25(useDIP25), + useDIP1000(useDIP1000), + ehnogc(ehnogc), + useDIP1021(useDIP1021), + fieldwise(fieldwise), + fixAliasThis(fixAliasThis), + rvalueRefParam(rvalueRefParam), + noSharedAccess(noSharedAccess), + previewIn(previewIn), + inclusiveInContracts(inclusiveInContracts), + shortenedMethods(shortenedMethods), + fixImmutableConv(fixImmutableConv), + fix16997(fix16997), + dtorFields(dtorFields), + systemVariables(systemVariables), + useInvariants(useInvariants), + useIn(useIn), + useOut(useOut), + useArrayBounds(useArrayBounds), + useAssert(useAssert), + useSwitchError(useSwitchError), + boundscheck(boundscheck), + checkAction(checkAction), + argv0(argv0), + modFileAliasStrings(modFileAliasStrings), + imppath(imppath), + fileImppath(fileImppath), + objdir(objdir), + objname(objname), + libname(libname), + ddoc(ddoc), + dihdr(dihdr), + cxxhdr(cxxhdr), + json(json), + jsonFieldFlags(jsonFieldFlags), + makeDeps(makeDeps), + mixinOut(mixinOut), + moduleDeps(moduleDeps), + debuglevel(debuglevel), + versionlevel(versionlevel), + run(run), + runargs(runargs), + cppswitches(cppswitches), + cpp(cpp), + objfiles(objfiles), + linkswitches(linkswitches), + linkswitchIsForCC(linkswitchIsForCC), + libfiles(libfiles), + dllfiles(dllfiles), + deffile(deffile), + resfile(resfile), + exefile(exefile), + mapfile(mapfile) + {} }; -extern void semantic2(Dsymbol* dsym, Scope* sc); - -extern void semantic3(Dsymbol* dsym, Scope* sc); - -extern void semanticTypeInfoMembers(StructDeclaration* sd); - -extern Statement* statementSemantic(Statement* s, Scope* sc); - -struct Target final +struct Global final { - enum class OS : uint8_t - { - none = 0u, - linux = 1u, - Windows = 2u, - OSX = 4u, - OpenBSD = 8u, - FreeBSD = 16u, - Solaris = 32u, - DragonFlyBSD = 64u, - all = 127u, - Posix = 125u, - }; - - OS os; - uint8_t osMajor; - uint8_t ptrsize; - uint8_t realsize; - uint8_t realpad; - uint8_t realalignsize; - uint8_t classinfosize; - uint64_t maxStaticDataSize; - TargetC c; - TargetCPP cpp; - TargetObjC objc; - _d_dynamicArray< const char > architectureName; - CPU cpu; - bool isX86_64; - bool isLP64; - _d_dynamicArray< const char > obj_ext; - _d_dynamicArray< const char > lib_ext; - _d_dynamicArray< const char > dll_ext; - bool run_noext; - bool omfobj; - template - struct FPTypeProperties final - { - real_t max; - real_t min_normal; - real_t nan; - real_t infinity; - real_t epsilon; - int64_t dig; - int64_t mant_dig; - int64_t max_exp; - int64_t min_exp; - int64_t max_10_exp; - int64_t min_10_exp; - FPTypeProperties() - { - } - }; - - FPTypeProperties FloatProperties; - FPTypeProperties DoubleProperties; - FPTypeProperties<_d_real > RealProperties; -private: - Type* tvalist; - const Param* params; -public: - void _init(const Param& params); - void setCPU(); - void deinitialize(); - uint32_t alignsize(Type* type); - uint32_t fieldalign(Type* type); - Type* va_listType(const Loc& loc, Scope* sc); - int32_t isVectorTypeSupported(int32_t sz, Type* type); - bool isVectorOpSupported(Type* type, EXP op, Type* t2 = nullptr); - LINK systemLinkage(); - TypeTuple* toArgTypes(Type* t); - bool isReturnOnStack(TypeFunction* tf, bool needsThis); - bool preferPassByRef(Type* t); -private: - enum class TargetInfoKeys - { - cppRuntimeLibrary = 0, - cppStd = 1, - floatAbi = 2, - objectFormat = 3, - CET = 4, - }; + _d_dynamicArray< const char > inifilename; + _d_dynamicArray< const char > copyright; + _d_dynamicArray< const char > written; + Array* path; + Array* filePath; + char datetime[26LLU]; + CompileEnv compileEnv; + Param params; + uint32_t errors; + uint32_t warnings; + uint32_t gag; + uint32_t gaggedErrors; + uint32_t gaggedWarnings; + void* console; + Array* versionids; + Array* debugids; + bool hasMainFunction; + uint32_t varSequenceNumber; + FileManager* fileManager; + enum : int32_t { recursionLimit = 500 }; -public: - Expression* getTargetInfo(const char* name, const Loc& loc); - bool isCalleeDestroyingArgs(TypeFunction* tf); - bool libraryObjectMonitors(FuncDeclaration* fd, Statement* fbody); - bool supportsLinkerDirective() const; - Target() : - os((OS)1u), - osMajor(0u), - ptrsize(), - realsize(), - realpad(), - realalignsize(), - classinfosize(), - maxStaticDataSize(), - c(), - cpp(), - objc(), - architectureName(), - cpu((CPU)11u), - isX86_64(true), - isLP64(), - obj_ext(), - lib_ext(), - dll_ext(), - run_noext(), - omfobj(false), - FloatProperties(), - DoubleProperties(), - RealProperties(), - tvalist(), - params() + ErrorSink* errorSink; + ErrorSink* errorSinkNull; + FileName(*preprocess)(FileName , const Loc& , bool& , OutBuffer* ); + uint32_t startGagging(); + bool endGagging(uint32_t oldGagged); + void increaseErrorCount(); + void _init(); + uint32_t versionNumber(); + const char* const versionChars(); + Global() : + inifilename(), + copyright(73, "Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved"), + written(24, "written by Walter Bright"), + path(), + filePath(), + compileEnv(), + params(), + errors(), + warnings(), + gag(), + gaggedErrors(), + gaggedWarnings(), + console(), + versionids(), + debugids(), + hasMainFunction(), + varSequenceNumber(1u), + fileManager(), + errorSink(), + errorSinkNull(), + preprocess() { } - Target(OS os, uint8_t osMajor = 0u, uint8_t ptrsize = 0u, uint8_t realsize = 0u, uint8_t realpad = 0u, uint8_t realalignsize = 0u, uint8_t classinfosize = 0u, uint64_t maxStaticDataSize = 0LLU, TargetC c = TargetC(), TargetCPP cpp = TargetCPP(), TargetObjC objc = TargetObjC(), _d_dynamicArray< const char > architectureName = {}, CPU cpu = (CPU)11u, bool isX86_64 = true, bool isLP64 = false, _d_dynamicArray< const char > obj_ext = {}, _d_dynamicArray< const char > lib_ext = {}, _d_dynamicArray< const char > dll_ext = {}, bool run_noext = false, bool omfobj = false, FPTypeProperties FloatProperties = FPTypeProperties(), FPTypeProperties DoubleProperties = FPTypeProperties(), FPTypeProperties<_d_real > RealProperties = FPTypeProperties<_d_real >(), Type* tvalist = nullptr, const Param* params = nullptr) : - os(os), - osMajor(osMajor), - ptrsize(ptrsize), - realsize(realsize), - realpad(realpad), - realalignsize(realalignsize), - classinfosize(classinfosize), - maxStaticDataSize(maxStaticDataSize), - c(c), - cpp(cpp), - objc(objc), - architectureName(architectureName), - cpu(cpu), - isX86_64(isX86_64), - isLP64(isLP64), - obj_ext(obj_ext), - lib_ext(lib_ext), - dll_ext(dll_ext), - run_noext(run_noext), - omfobj(omfobj), - FloatProperties(FloatProperties), - DoubleProperties(DoubleProperties), - RealProperties(RealProperties), - tvalist(tvalist), - params(params) + Global(_d_dynamicArray< const char > inifilename, _d_dynamicArray< const char > copyright = { 73, "Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved" }, _d_dynamicArray< const char > written = { 24, "written by Walter Bright" }, Array* path = nullptr, Array* filePath = nullptr, CompileEnv compileEnv = CompileEnv(), Param params = Param(), uint32_t errors = 0u, uint32_t warnings = 0u, uint32_t gag = 0u, uint32_t gaggedErrors = 0u, uint32_t gaggedWarnings = 0u, void* console = nullptr, Array* versionids = nullptr, Array* debugids = nullptr, bool hasMainFunction = false, uint32_t varSequenceNumber = 1u, FileManager* fileManager = nullptr, ErrorSink* errorSink = nullptr, ErrorSink* errorSinkNull = nullptr, FileName(*preprocess)(FileName , const Loc& , bool& , OutBuffer* ) = nullptr) : + inifilename(inifilename), + copyright(copyright), + written(written), + path(path), + filePath(filePath), + compileEnv(compileEnv), + params(params), + errors(errors), + warnings(warnings), + gag(gag), + gaggedErrors(gaggedErrors), + gaggedWarnings(gaggedWarnings), + console(console), + versionids(versionids), + debugids(debugids), + hasMainFunction(hasMainFunction), + varSequenceNumber(varSequenceNumber), + fileManager(fileManager), + errorSink(errorSink), + errorSinkNull(errorSinkNull), + preprocess(preprocess) {} }; -extern Target target; - -extern bool tpsemantic(TemplateParameter* tp, Scope* sc, Array* parameters); - -extern bool genTypeInfo(Expression* e, const Loc& loc, Type* torig, Scope* sc); - -extern Type* getTypeInfoType(const Loc& loc, Type* t, Scope* sc, bool genObjCode = true); - -extern bool isSpeculativeType(Type* t); - -extern bool builtinTypeInfo(Type* t); - -class SemanticTimeTransitiveVisitor : public SemanticTimePermissiveVisitor -{ -public: - using SemanticTimePermissiveVisitor::visit; - void visit(ExpStatement* s) override; - void visit(MixinStatement* s) override; - void visit(CompoundStatement* s) override; - virtual void visitVarDecl(VarDeclaration* v); - void visit(CompoundDeclarationStatement* s) override; - void visit(ScopeStatement* s) override; - void visit(WhileStatement* s) override; - void visit(DoStatement* s) override; - void visit(ForStatement* s) override; - void visit(ForeachStatement* s) override; - void visit(ForeachRangeStatement* s) override; - void visit(StaticForeachStatement* s) override; - void visit(IfStatement* s) override; - void visit(ConditionalStatement* s) override; - void visit(PragmaStatement* s) override; - void visit(StaticAssertStatement* s) override; - void visit(SwitchStatement* s) override; - void visit(CaseStatement* s) override; - void visit(CaseRangeStatement* s) override; - void visit(DefaultStatement* s) override; - void visit(GotoCaseStatement* s) override; - void visit(ReturnStatement* s) override; - void visit(SynchronizedStatement* s) override; - void visit(WithStatement* s) override; - void visit(TryCatchStatement* s) override; - void visit(TryFinallyStatement* s) override; - void visit(ScopeGuardStatement* s) override; - void visit(ThrowStatement* s) override; - void visit(LabelStatement* s) override; - void visit(ImportStatement* s) override; - virtual void visit(Catch* c); - virtual void visitType(Type* t); - virtual void visitFunctionType(TypeFunction* t, TemplateDeclaration* td); - void visit(TypeVector* t) override; - void visit(TypeSArray* t) override; - void visit(TypeDArray* t) override; - void visit(TypeAArray* t) override; - void visit(TypePointer* t) override; - void visit(TypeReference* t) override; - void visit(TypeFunction* t) override; - void visit(TypeDelegate* t) override; - virtual void visitTypeQualified(TypeQualified* t); - void visit(TypeIdentifier* t) override; - void visit(TypeInstance* t) override; - void visit(TypeTypeof* t) override; - void visit(TypeReturn* t) override; - void visit(TypeTuple* t) override; - void visit(TypeSlice* t) override; - void visit(TypeTraits* t) override; - void visit(TypeMixin* t) override; - void visit(StaticAssert* s) override; - void visit(EnumMember* em) override; - virtual void visitAttribDeclaration(AttribDeclaration* d); - void visit(AttribDeclaration* d) override; - void visit(StorageClassDeclaration* d) override; - void visit(DeprecatedDeclaration* d) override; - void visit(LinkDeclaration* d) override; - void visit(CPPMangleDeclaration* d) override; - void visit(VisibilityDeclaration* d) override; - void visit(AlignDeclaration* d) override; - void visit(AnonDeclaration* d) override; - void visit(PragmaDeclaration* d) override; - void visit(ConditionalDeclaration* d) override; - void visit(MixinDeclaration* d) override; - void visit(UserAttributeDeclaration* d) override; - virtual void visitFuncBody(FuncDeclaration* f); - virtual void visitBaseClasses(ClassDeclaration* d); - virtual bool visitEponymousMember(TemplateDeclaration* d); - virtual void visitTemplateParameters(Array* parameters); - void visit(TemplateDeclaration* d) override; - virtual void visitObject(RootObject* oarg); - virtual void visitTiargs(TemplateInstance* ti); - void visit(TemplateInstance* ti) override; - void visit(TemplateMixin* tm) override; - void visit(EnumDeclaration* d) override; - void visit(Nspace* d) override; - void visit(StructDeclaration* d) override; - void visit(UnionDeclaration* d) override; - void visit(ClassDeclaration* d) override; - void visit(InterfaceDeclaration* d) override; - void visit(AliasDeclaration* d) override; - void visit(AliasAssign* d) override; - void visit(VarDeclaration* d) override; - void visit(FuncDeclaration* f) override; - void visit(FuncLiteralDeclaration* f) override; - void visit(PostBlitDeclaration* d) override; - void visit(DtorDeclaration* d) override; - void visit(CtorDeclaration* d) override; - void visit(StaticCtorDeclaration* d) override; - void visit(StaticDtorDeclaration* d) override; - void visit(InvariantDeclaration* d) override; - void visit(UnitTestDeclaration* d) override; - void visit(NewDeclaration* d) override; - void visit(StructInitializer* si) override; - void visit(ArrayInitializer* ai) override; - void visit(ExpInitializer* ei) override; - void visit(CInitializer* ci) override; - void visit(ArrayLiteralExp* e) override; - void visit(AssocArrayLiteralExp* e) override; - void visit(TypeExp* e) override; - void visit(ScopeExp* e) override; - void visit(NewExp* e) override; - void visit(NewAnonClassExp* e) override; - void visit(TupleExp* e) override; - void visit(FuncExp* e) override; - void visit(DeclarationExp* e) override; - void visit(TypeidExp* e) override; - void visit(TraitsExp* e) override; - void visit(IsExp* e) override; - void visit(UnaExp* e) override; - void visit(BinExp* e) override; - void visit(MixinExp* e) override; - void visit(ImportExp* e) override; - void visit(AssertExp* e) override; - void visit(DotIdExp* e) override; - void visit(DotTemplateInstanceExp* e) override; - void visit(CallExp* e) override; - void visit(PtrExp* e) override; - void visit(DeleteExp* e) override; - void visit(CastExp* e) override; - void visit(IntervalExp* e) override; - void visit(ArrayExp* e) override; - void visit(PostExp* e) override; - void visit(CondExp* e) override; - void visit(GenericExp* e) override; - void visit(ThrowExp* e) override; - void visit(TemplateTypeParameter* tp) override; - void visit(TemplateThisParameter* tp) override; - void visit(TemplateAliasParameter* tp) override; - void visit(TemplateValueParameter* tp) override; - void visit(StaticIfCondition* c) override; - void visit(Parameter* p) override; - void visit(Module* m) override; - void visit(PeelStatement* s) override; - void visit(UnrolledLoopStatement* s) override; - void visit(DebugStatement* s) override; - void visit(ForwardingStatement* s) override; - void visit(StructLiteralExp* e) override; - void visit(CompoundLiteralExp* e) override; - void visit(DotTemplateExp* e) override; - void visit(DotVarExp* e) override; - void visit(DelegateExp* e) override; - void visit(DotTypeExp* e) override; - void visit(VectorExp* e) override; - void visit(VectorArrayExp* e) override; - void visit(SliceExp* e) override; - void visit(ArrayLengthExp* e) override; - void visit(DelegatePtrExp* e) override; - void visit(DelegateFuncptrExp* e) override; - void visit(DotExp* e) override; - void visit(IndexExp* e) override; - void visit(RemoveExp* e) override; - void visit(LoweredAssignExp* e) override; -}; - -extern _d_real creall(complex_t x); - -extern _d_real cimagl(complex_t x); - -extern void browse(const char* url); - -extern void error(const Loc& loc, const char* format, ...); - -extern void error(const char* filename, uint32_t linnum, uint32_t charnum, const char* format, ...); - -extern void errorSupplemental(const Loc& loc, const char* format, ...); - -extern void warning(const Loc& loc, const char* format, ...); - -extern void warningSupplemental(const Loc& loc, const char* format, ...); - -extern void deprecation(const Loc& loc, const char* format, ...); - -extern void deprecationSupplemental(const Loc& loc, const char* format, ...); - -extern void message(const Loc& loc, const char* format, ...); - -extern void message(const char* format, ...); - -extern void tip(const char* format, ...); - -extern void verrorReport(const Loc& loc, const char* format, va_list ap, ErrorKind kind, const char* p1 = nullptr, const char* p2 = nullptr); - -extern void verrorReportSupplemental(const Loc& loc, const char* format, va_list ap, ErrorKind kind); - -extern void fatal(); - -extern void halt(); +extern Global global; struct Id final { diff --git a/dmd/hdrgen.d b/dmd/hdrgen.d index cdaad5d4a44..608d468b929 100644 --- a/dmd/hdrgen.d +++ b/dmd/hdrgen.d @@ -3434,7 +3434,7 @@ private void parameterToBuffer(Parameter p, ref OutBuffer buf, ref HdrGenState h if (p.storageClass & STC.in_) { buf.writestring("in "); - if (global.params.previewIn && p.storageClass & STC.ref_) + if ((p.storageClass & (STC.constscoperef | STC.ref_)) == (STC.constscoperef | STC.ref_)) stc &= ~STC.ref_; } else if (p.storageClass & STC.lazy_) diff --git a/dmd/mtype.d b/dmd/mtype.d index 60ede9d6aa6..6a3e43ddf73 100644 --- a/dmd/mtype.d +++ b/dmd/mtype.d @@ -525,7 +525,7 @@ extern (C++) abstract class Type : ASTNode */ final override const(char)* toChars() const { - return dmd.hdrgen.toChars(this); + return dmd.hdrgen.toChars(this); } /// ditto @@ -4135,7 +4135,7 @@ extern (C++) final class TypeFunction : TypeNext auto stc = p.storageClass; // When the preview switch is enable, `in` parameters are `scope` - if (stc & STC.in_ && global.params.previewIn) + if (stc & STC.constscoperef) return stc | STC.scope_; if (stc & (STC.scope_ | STC.return_ | STC.lazy_) || purity == PURE.impure) @@ -6427,28 +6427,22 @@ extern (C++) final class Parameter : ASTNode * Params: * returnByRef = true if the function returns by ref * p = Parameter to compare with - * previewIn = Whether `-preview=in` is being used, and thus if - * `in` means `scope [ref]`. - * * Returns: * true = `this` can be used in place of `p` * false = nope */ - bool isCovariant(bool returnByRef, const Parameter p, bool previewIn = global.params.previewIn) + bool isCovariant(bool returnByRef, const Parameter p) const pure nothrow @nogc @safe { ulong thisSTC = this.storageClass; ulong otherSTC = p.storageClass; - if (previewIn) - { - if (thisSTC & STC.in_) - thisSTC |= STC.scope_; - if (otherSTC & STC.in_) - otherSTC |= STC.scope_; - } + if (thisSTC & STC.constscoperef) + thisSTC |= STC.scope_; + if (otherSTC & STC.constscoperef) + otherSTC |= STC.scope_; - const mask = STC.ref_ | STC.out_ | STC.lazy_ | (previewIn ? STC.in_ : 0); + const mask = STC.ref_ | STC.out_ | STC.lazy_ | (((thisSTC | otherSTC) & STC.constscoperef) ? STC.in_ : 0); if ((thisSTC & mask) != (otherSTC & mask)) return false; return isCovariantScope(returnByRef, thisSTC, otherSTC); diff --git a/dmd/parse.d b/dmd/parse.d index b6f30b93f47..2797a778bfd 100644 --- a/dmd/parse.d +++ b/dmd/parse.d @@ -2899,6 +2899,8 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer if (transitionIn) eSink.message(scanloc, "Usage of 'in' on parameter"); stc = STC.in_; + if (compileEnv.previewIn) + stc |= STC.constscoperef; goto L2; case TOK.out_: @@ -2936,9 +2938,9 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer default: { - stc = storageClass & (STC.IOR | STC.lazy_); - // if stc is not a power of 2 - if (stc & (stc - 1) && !(stc == (STC.in_ | STC.ref_))) + const stcx = storageClass & (STC.in_ | STC.ref_ | STC.out_ | STC.lazy_); + // if stcx is not a power of 2 + if (stcx & (stcx - 1) && !(stcx == (STC.in_ | STC.ref_))) error("incompatible parameter storage classes"); //if ((storageClass & STC.scope_) && (storageClass & (STC.ref_ | STC.out_))) //error("scope cannot be ref or out"); diff --git a/dmd/typesem.d b/dmd/typesem.d index 574e54cfb7b..d70f3fd5af8 100644 --- a/dmd/typesem.d +++ b/dmd/typesem.d @@ -843,7 +843,7 @@ private extern(D) MATCH argumentMatchParameter (TypeFunction tf, Parameter p, ta = tn.sarrayOf(dim); } } - else if ((p.storageClass & STC.in_) && global.params.previewIn) + else if (p.storageClass & STC.constscoperef) { // Allow converting a literal to an `in` which is `ref` if (arg.op == EXP.arrayLiteral && tp.ty == Tsarray) @@ -1678,7 +1678,7 @@ extern(C++) Type typeSemantic(Type type, const ref Loc loc, Scope* sc) // default arg must be an lvalue if (isRefOrOut && !isAuto && - !(global.params.previewIn && (fparam.storageClass & STC.in_)) && + !(fparam.storageClass & STC.constscoperef) && global.params.rvalueRefParam != FeatureState.enabled) e = e.toLvalue(sc, "create default argument for `ref` / `out` parameter from"); @@ -1784,13 +1784,13 @@ extern(C++) Type typeSemantic(Type type, const ref Loc loc, Scope* sc) switch (tf.linkage) { case LINK.cpp: - if (global.params.previewIn) + if (fparam.storageClass & STC.constscoperef) fparam.storageClass |= STC.ref_; break; case LINK.default_, LINK.d: break; default: - if (global.params.previewIn) + if (fparam.storageClass & STC.constscoperef) { .error(loc, "cannot use `in` parameters with `extern(%s)` functions", linkageToChars(tf.linkage)); @@ -1820,7 +1820,7 @@ extern(C++) Type typeSemantic(Type type, const ref Loc loc, Scope* sc) if (tb2.ty == Tstruct && !tb2.isTypeStruct().sym.members || tb2.ty == Tenum && !tb2.isTypeEnum().sym.memtype) { - if (global.params.previewIn && (fparam.storageClass & STC.in_)) + if (fparam.storageClass & STC.constscoperef) { .error(loc, "cannot infer `ref` for `in` parameter `%s` of opaque type `%s`", fparam.toChars(), fparam.type.toChars()); @@ -1902,7 +1902,7 @@ extern(C++) Type typeSemantic(Type type, const ref Loc loc, Scope* sc) fparam.storageClass &= ~(STC.TYPECTOR); // -preview=in: add `ref` storage class to suited `in` params - if (global.params.previewIn && (fparam.storageClass & (STC.in_ | STC.ref_)) == STC.in_) + if ((fparam.storageClass & (STC.constscoperef | STC.ref_)) == STC.constscoperef) { auto ts = t.baseElemOf().isTypeStruct(); const isPOD = !ts || ts.sym.isPOD(); From dbf82774ef1ec4af37c43b871a8a4f898ddb7b92 Mon Sep 17 00:00:00 2001 From: Walter Bright Date: Thu, 21 Dec 2023 20:36:16 -0800 Subject: [PATCH 147/215] hdrgen.d: remove globals.d import --- dmd/hdrgen.d | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/dmd/hdrgen.d b/dmd/hdrgen.d index 608d468b929..35bb2a6be26 100644 --- a/dmd/hdrgen.d +++ b/dmd/hdrgen.d @@ -35,7 +35,6 @@ import dmd.dtemplate; import dmd.dversion; import dmd.expression; import dmd.func; -import dmd.globals; import dmd.id; import dmd.identifier; import dmd.init; @@ -2067,7 +2066,7 @@ private void expressionPrettyPrint(Expression e, ref OutBuffer buf, ref HdrGenSt void visitInteger(IntegerExp e) { - const dinteger_t v = e.toInteger(); + const ulong v = e.toInteger(); if (e.type) { Type t = e.type; @@ -2161,11 +2160,8 @@ private void expressionPrettyPrint(Expression e, ref OutBuffer buf, ref HdrGenSt default: /* This can happen if errors, such as * the type is painted on like in fromConstInitializer(). + * Just ignore */ - if (!global.errors) - { - assert(0); - } break; } } @@ -3540,10 +3536,10 @@ private void sizeToBuffer(Expression e, ref OutBuffer buf, ref HdrGenState hgs) { Expression ex = (e.op == EXP.cast_ ? (cast(CastExp)e).e1 : e); ex = ex.optimize(WANTvalue); - const dinteger_t uval = ex.op == EXP.int64 ? ex.toInteger() : cast(dinteger_t)-1; - if (cast(sinteger_t)uval >= 0) + const ulong uval = ex.op == EXP.int64 ? ex.toInteger() : cast(ulong)-1; + if (cast(long)uval >= 0) { - dinteger_t sizemax = void; + ulong sizemax = void; if (target.ptrsize == 8) sizemax = 0xFFFFFFFFFFFFFFFFUL; else if (target.ptrsize == 4) From e125a0cb1b5bd29d757e36f87da9118fd3af6c83 Mon Sep 17 00:00:00 2001 From: Dennis Date: Fri, 22 Dec 2023 20:03:03 +0100 Subject: [PATCH 148/215] Add `@standalone` attribute for module constructors (dlang/dmd!15537) * Add `@__standalone` attribute * Remove underscores from __standalone --- dmd/attrib.d | 24 +++++++++++++++++++ dmd/declaration.h | 1 + dmd/dsymbolsem.d | 18 ++++++++++++++ dmd/frontend.h | 2 ++ dmd/func.d | 3 +++ dmd/id.d | 1 + dmd/mustuse.d | 17 ++----------- runtime/druntime/src/core/attribute.d | 12 ++++++++++ .../dmd/fail_compilation/standalone_modctor.d | 15 ++++++++++++ tests/dmd/runnable/imports/standalone_b.d | 11 +++++++++ tests/dmd/runnable/standalone_modctor.d | 19 +++++++++++++++ 11 files changed, 108 insertions(+), 15 deletions(-) create mode 100644 tests/dmd/fail_compilation/standalone_modctor.d create mode 100644 tests/dmd/runnable/imports/standalone_b.d create mode 100644 tests/dmd/runnable/standalone_modctor.d diff --git a/dmd/attrib.d b/dmd/attrib.d index c37ac01e711..f81dcf4701b 100644 --- a/dmd/attrib.d +++ b/dmd/attrib.d @@ -1296,3 +1296,27 @@ int foreachUdaNoSemantic(Dsymbol sym, int delegate(Expression) dg) return 0; } + + +/** + * Returns: true if the given expression is an enum from `core.attribute` named `id` + */ +bool isEnumAttribute(Expression e, Identifier id) +{ + import dmd.attrib : isCoreUda; + import dmd.id : Id; + + // Logic based on dmd.objc.Supported.declaredAsOptionalCount + auto typeExp = e.isTypeExp; + if (!typeExp) + return false; + + auto typeEnum = typeExp.type.isTypeEnum(); + if (!typeEnum) + return false; + + if (isCoreUda(typeEnum.sym, id)) + return true; + + return false; +} diff --git a/dmd/declaration.h b/dmd/declaration.h index 83474736f71..6b23f70e2bd 100644 --- a/dmd/declaration.h +++ b/dmd/declaration.h @@ -843,6 +843,7 @@ class StaticCtorDeclaration : public FuncDeclaration class SharedStaticCtorDeclaration final : public StaticCtorDeclaration { public: + bool standalone; SharedStaticCtorDeclaration *syntaxCopy(Dsymbol *) override; SharedStaticCtorDeclaration *isSharedStaticCtorDeclaration() override { return this; } diff --git a/dmd/dsymbolsem.d b/dmd/dsymbolsem.d index 3e1a5af719d..a015fb39224 100644 --- a/dmd/dsymbolsem.d +++ b/dmd/dsymbolsem.d @@ -4592,6 +4592,24 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor m.needmoduleinfo = 1; //printf("module1 %s needs moduleinfo\n", m.toChars()); } + + foreachUda(scd, sc, (Expression e) { + import dmd.attrib : isEnumAttribute; + if (!isEnumAttribute(e, Id.udaStandalone)) + return 0; + + if (auto sharedCtor = scd.isSharedStaticCtorDeclaration()) + { + auto trust = sharedCtor.type.isTypeFunction().trust; + if (trust != TRUST.system && trust != TRUST.trusted) + error(e.loc, "a module constructor using `@%s` must be `@system` or `@trusted`", Id.udaStandalone.toChars()); + sharedCtor.standalone = true; + } + else + .error(e.loc, "`@%s` can only be used on shared static constructors", Id.udaStandalone.toChars()); + + return 1; + }); } override void visit(StaticDtorDeclaration sdd) diff --git a/dmd/frontend.h b/dmd/frontend.h index b55cfb49380..6e2bf5ac062 100644 --- a/dmd/frontend.h +++ b/dmd/frontend.h @@ -4005,6 +4005,7 @@ class StaticCtorDeclaration : public FuncDeclaration class SharedStaticCtorDeclaration final : public StaticCtorDeclaration { public: + bool standalone; SharedStaticCtorDeclaration* syntaxCopy(Dsymbol* s) override; SharedStaticCtorDeclaration* isSharedStaticCtorDeclaration() override; void accept(Visitor* v) override; @@ -8825,6 +8826,7 @@ struct Id final static Identifier* udaSelector; static Identifier* udaOptional; static Identifier* udaMustUse; + static Identifier* udaStandalone; static Identifier* TRUE; static Identifier* FALSE; static Identifier* ImportC; diff --git a/dmd/func.d b/dmd/func.d index feaa5bb4d91..0889ea26a97 100644 --- a/dmd/func.d +++ b/dmd/func.d @@ -4253,6 +4253,9 @@ extern (C++) class StaticCtorDeclaration : FuncDeclaration */ extern (C++) final class SharedStaticCtorDeclaration : StaticCtorDeclaration { + /// Exclude this constructor from cyclic dependency check + bool standalone; + extern (D) this(const ref Loc loc, const ref Loc endloc, StorageClass stc) { super(loc, endloc, "_sharedStaticCtor", stc); diff --git a/dmd/id.d b/dmd/id.d index 32221d94744..d639b70141e 100644 --- a/dmd/id.d +++ b/dmd/id.d @@ -521,6 +521,7 @@ immutable Msgtable[] msgtable = { "udaSelector", "selector" }, { "udaOptional", "optional"}, { "udaMustUse", "mustuse" }, + { "udaStandalone", "standalone" }, // C names, for undefined identifier error messages { "NULL" }, diff --git a/dmd/mustuse.d b/dmd/mustuse.d index 693464919e0..83b63042cb7 100644 --- a/dmd/mustuse.d +++ b/dmd/mustuse.d @@ -222,20 +222,7 @@ private bool hasMustUseAttribute(Dsymbol sym, Scope* sc) */ private bool isMustUseAttribute(Expression e) { - import dmd.attrib : isCoreUda; + import dmd.attrib : isEnumAttribute; import dmd.id : Id; - - // Logic based on dmd.objc.Supported.declaredAsOptionalCount - auto typeExp = e.isTypeExp; - if (!typeExp) - return false; - - auto typeEnum = typeExp.type.isTypeEnum(); - if (!typeEnum) - return false; - - if (isCoreUda(typeEnum.sym, Id.udaMustUse)) - return true; - - return false; + return isEnumAttribute(e, Id.udaMustUse); } diff --git a/runtime/druntime/src/core/attribute.d b/runtime/druntime/src/core/attribute.d index c2a7c334eb7..79ad25ab358 100644 --- a/runtime/druntime/src/core/attribute.d +++ b/runtime/druntime/src/core/attribute.d @@ -290,3 +290,15 @@ version (UdaGNUAbiTag) struct gnuAbiTag * --- */ enum mustuse; + +/** + * Use this attribute to indicate that a shared module constructor does not depend on any + * other module constructor being run first. This avoids errors on cyclic module constructors. + * + * However, it is now up to the user to enforce safety. + * The module constructor must be marked `@system` as a result. + * Prefer to refactor the module constructor causing the cycle so it's in its own module if possible. + * + * This is only allowed on `shared` static constructors, not thread-local module constructors. + */ +enum standalone; diff --git a/tests/dmd/fail_compilation/standalone_modctor.d b/tests/dmd/fail_compilation/standalone_modctor.d new file mode 100644 index 00000000000..cb36ed6b790 --- /dev/null +++ b/tests/dmd/fail_compilation/standalone_modctor.d @@ -0,0 +1,15 @@ +/** +TEST_OUTPUT: +--- +fail_compilation/standalone_modctor.d(11): Error: `@standalone` can only be used on shared static constructors +fail_compilation/standalone_modctor.d(12): Error: a module constructor using `@standalone` must be `@system` or `@trusted` +fail_compilation/standalone_modctor.d(13): Error: a module constructor using `@standalone` must be `@system` or `@trusted` +--- +*/ +import core.attribute : standalone; + +@standalone static this() {} +@standalone shared static this() {} +@standalone shared static this() @safe {} +@standalone shared static this() @trusted {} +@standalone shared static this() @system {} diff --git a/tests/dmd/runnable/imports/standalone_b.d b/tests/dmd/runnable/imports/standalone_b.d new file mode 100644 index 00000000000..bc5500b7b8c --- /dev/null +++ b/tests/dmd/runnable/imports/standalone_b.d @@ -0,0 +1,11 @@ +module standalone_b; + +import standalone_modctor; +import core.attribute : standalone; + +immutable int* y; + +@standalone @system shared static this() +{ + y = new int(2); +} diff --git a/tests/dmd/runnable/standalone_modctor.d b/tests/dmd/runnable/standalone_modctor.d new file mode 100644 index 00000000000..26544076836 --- /dev/null +++ b/tests/dmd/runnable/standalone_modctor.d @@ -0,0 +1,19 @@ +// REQUIRED_ARGS: -Irunnable/imports +// EXTRA_SOURCES: imports/standalone_b.d +// PERMUTE_ARGS: -cov + +import standalone_b; +import core.attribute : standalone; + +immutable int* x; + +@standalone @system shared static this() +{ + x = new int(1); +} + +void main() +{ + assert(*x == 1); + assert(*y == 2); +} From 1042698323b6c176e9aef9ff7210eb659b369297 Mon Sep 17 00:00:00 2001 From: Tim Schendekehl Date: Fri, 22 Dec 2023 14:12:11 +0100 Subject: [PATCH 149/215] Fix issue 24298 - cpp_delete should check for null The delete operator in C++ can be called with a null pointer and ignores it. This commit makes cpp_delete consistent with C++, so null pointers are also ignored. --- runtime/druntime/src/core/stdcpp/new_.d | 4 ++ runtime/druntime/test/stdcpp/src/new_test.d | 53 +++++++++++++++++++++ 2 files changed, 57 insertions(+) diff --git a/runtime/druntime/src/core/stdcpp/new_.d b/runtime/druntime/src/core/stdcpp/new_.d index 6a598baec28..de9e10ac47c 100644 --- a/runtime/druntime/src/core/stdcpp/new_.d +++ b/runtime/druntime/src/core/stdcpp/new_.d @@ -59,6 +59,8 @@ T cpp_new(T, Args...)(auto ref Args args) if (is(T == class)) /// void cpp_delete(T)(T* ptr) if (!is(T == class)) { + if (ptr is null) + return; destroy!false(*ptr); __cpp_delete(ptr); } @@ -66,6 +68,8 @@ void cpp_delete(T)(T* ptr) if (!is(T == class)) /// void cpp_delete(T)(T instance) if (is(T == class)) { + if (instance is null) + return; destroy!false(instance); __cpp_delete(cast(void*) instance); } diff --git a/runtime/druntime/test/stdcpp/src/new_test.d b/runtime/druntime/test/stdcpp/src/new_test.d index 5e91c2bf097..b91967e5a9d 100644 --- a/runtime/druntime/test/stdcpp/src/new_test.d +++ b/runtime/druntime/test/stdcpp/src/new_test.d @@ -135,3 +135,56 @@ unittest assert(MyClassGC.numDeleted == 1); } } + +unittest +{ + import core.stdcpp.new_: cpp_new, cpp_delete; + + { + extern(C++) static struct S + { + __gshared int numDeleted; + __gshared int lastDeleted; + int i; + ~this() + { + lastDeleted = i; + numDeleted++; + } + } + S *s = cpp_new!S(12345); + cpp_delete(s); + assert(S.numDeleted == 1); + assert(S.lastDeleted == 12345); + s = null; + cpp_delete(s); + assert(S.numDeleted == 1); + assert(S.lastDeleted == 12345); + } + + { + extern(C++) static class C + { + __gshared int numDeleted; + __gshared int lastDeleted; + int i; + this(int i) + { + this.i = i; + } + ~this() + { + lastDeleted = i; + numDeleted++; + } + } + C c = cpp_new!C(54321); + cpp_delete(c); + assert(C.numDeleted == 1); + assert(C.lastDeleted == 54321); + c = null; + cpp_delete(c); + assert(C.numDeleted == 1); + assert(C.lastDeleted == 54321); + } +} From b209b9fe86b1df16ae85bd7677a3049359855f8d Mon Sep 17 00:00:00 2001 From: Martin Kinkelin Date: Fri, 22 Dec 2023 03:33:33 +0100 Subject: [PATCH 150/215] DMD tests on Windows: Default CC to cl.exe in PATH for MSVC models Instead of defaulting to some old hardcoded version. --- tests/dmd/tools/d_do_test.d | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/tests/dmd/tools/d_do_test.d b/tests/dmd/tools/d_do_test.d index b642c4d9932..62ec4ee46e7 100755 --- a/tests/dmd/tools/d_do_test.d +++ b/tests/dmd/tools/d_do_test.d @@ -138,7 +138,6 @@ struct EnvData bool coverage_build; /// `COVERAGE`: coverage build, skip linking & executing to save time bool autoUpdate; /// `AUTO_UPDATE`: update `(TEST|RUN)_OUTPUT` on missmatch bool printRuntime; /// `PRINT_RUNTIME`: Print time spent on a single test - bool usingMicrosoftCompiler; /// Using Visual Studio toolchain bool tryDisabled; /// `TRY_DISABLED`:Silently try disabled tests (ignore failure and report success) } @@ -198,9 +197,9 @@ immutable(EnvData) processEnvironment() else if (envData.model == "32omf") envData.ccompiler = "dmc"; else if (envData.model == "64") - envData.ccompiler = `C:\"Program Files (x86)"\"Microsoft Visual Studio 10.0"\VC\bin\amd64\cl.exe`; + envData.ccompiler = "cl"; else if (envData.model == "32mscoff") - envData.ccompiler = `C:\"Program Files (x86)"\"Microsoft Visual Studio 10.0"\VC\bin\amd64_x86\cl.exe`; + envData.ccompiler = "cl"; else { writeln("Unknown $OS$MODEL combination: ", envData.os, envData.model); @@ -208,8 +207,6 @@ immutable(EnvData) processEnvironment() } } - envData.usingMicrosoftCompiler = envData.ccompiler.toLower.endsWith("cl.exe"); - version (Windows) {} else { version(X86_64) @@ -1098,13 +1095,13 @@ bool collectExtraSources (in string input_dir, in string output_dir, in string[] auto curSrc = input_dir ~ envData.sep ~"extra-files" ~ envData.sep ~ cur; auto curObj = output_dir ~ envData.sep ~ cur ~ envData.obj; string command = quoteSpaces(compiler); - if (envData.usingMicrosoftCompiler) + if (envData.model == "32omf") // dmc.exe { - command ~= ` /c /nologo `~curSrc~` /Fo`~curObj; + command ~= " -c "~curSrc~" -o"~curObj; } - else if (envData.compiler == "dmd" && envData.os == "windows" && envData.model == "32omf") + else if (envData.os == "windows") // cl.exe { - command ~= " -c "~curSrc~" -o"~curObj; + command ~= ` /c /nologo `~curSrc~` /Fo`~curObj; } else { @@ -1832,7 +1829,7 @@ int tryMain(string[] args) { toCleanup ~= test_app_dmd; version(Windows) - if (envData.usingMicrosoftCompiler) + if (envData.model != "32omf") { toCleanup ~= test_app_dmd_base ~ to!string(permuteIndex) ~ ".ilk"; toCleanup ~= test_app_dmd_base ~ to!string(permuteIndex) ~ ".pdb"; From ec7a0ba0a1d1a2459fd25d448e8a46629f6fd0a6 Mon Sep 17 00:00:00 2001 From: Walter Bright Date: Fri, 22 Dec 2023 23:36:47 -0800 Subject: [PATCH 151/215] hdrgen.d: remove reference to global target --- dmd/hdrgen.d | 28 ++++++------------- tests/dmd/compilable/test9565.d | 4 +-- tests/dmd/fail_compilation/fail19890a.d | 4 +-- tests/dmd/fail_compilation/fail19890b.d | 4 +-- tests/dmd/fail_compilation/fail4611.d | 4 +-- .../fail_compilation/staticarrayoverflow.d | 6 ++-- 6 files changed, 20 insertions(+), 30 deletions(-) diff --git a/dmd/hdrgen.d b/dmd/hdrgen.d index 35bb2a6be26..6ad9c8f849d 100644 --- a/dmd/hdrgen.d +++ b/dmd/hdrgen.d @@ -49,7 +49,6 @@ import dmd.rootobject; import dmd.root.string; import dmd.statement; import dmd.staticassert; -import dmd.target; import dmd.tokens; import dmd.visitor; @@ -2144,14 +2143,8 @@ private void expressionPrettyPrint(Expression e, ref OutBuffer buf, ref HdrGenSt case Tpointer: buf.writestring("cast("); buf.writestring(t.toChars()); - buf.writeByte(')'); - if (target.ptrsize == 8) - goto case Tuns64; - else if (target.ptrsize == 4 || - target.ptrsize == 2) - goto case Tuns32; - else - assert(0); + buf.writestring(")cast(size_t)"); + goto case Tuns64; case Tvoid: buf.writestring("cast(void)0"); @@ -3539,17 +3532,14 @@ private void sizeToBuffer(Expression e, ref OutBuffer buf, ref HdrGenState hgs) const ulong uval = ex.op == EXP.int64 ? ex.toInteger() : cast(ulong)-1; if (cast(long)uval >= 0) { - ulong sizemax = void; - if (target.ptrsize == 8) - sizemax = 0xFFFFFFFFFFFFFFFFUL; - else if (target.ptrsize == 4) - sizemax = 0xFFFFFFFFU; - else if (target.ptrsize == 2) - sizemax = 0xFFFFU; - else - assert(0); - if (uval <= sizemax && uval <= 0x7FFFFFFFFFFFFFFFUL) + if (uval <= 0xFFFFU) + { + buf.print(uval); + return; + } + if (uval <= 0x7FFF_FFFF_FFFF_FFFFUL) { + buf.writestring("cast(size_t)"); buf.print(uval); return; } diff --git a/tests/dmd/compilable/test9565.d b/tests/dmd/compilable/test9565.d index 9e3ee6a8170..ef412f7e7d6 100644 --- a/tests/dmd/compilable/test9565.d +++ b/tests/dmd/compilable/test9565.d @@ -1,4 +1,4 @@ -// REQUIRED_ARGS: -o- +// REQUIRED_ARGS: -o- -m32 // PERMUTE_ARGS: template TypeTuple(T...) { alias TypeTuple = T; } @@ -30,7 +30,7 @@ void main() // index == NegExp static assert((arr[-4 ]).stringof == "arr[" ~ castPrefix ~ "-4]"); - static assert((arr[-4U ]).stringof == "arr[4294967292]"); + static assert((arr[-4U ]).stringof == "arr[cast(size_t)4294967292]"); static assert((arr[int.min] ).stringof == "arr[" ~ castPrefix ~ "-2147483648]"); static if (is(size_t == ulong)) { diff --git a/tests/dmd/fail_compilation/fail19890a.d b/tests/dmd/fail_compilation/fail19890a.d index 9b984961f33..2e8e4e6ae9c 100644 --- a/tests/dmd/fail_compilation/fail19890a.d +++ b/tests/dmd/fail_compilation/fail19890a.d @@ -1,7 +1,7 @@ -/* +/* REQUIRED_ARGS: -m32 TEST_OUTPUT: --- -fail_compilation/fail19890a.d(8): Error: `void[$n$$?:64=LU$]` size 1 * $n$ exceeds $?:windows+32omf=0x1000000|0x7fffffff$ size limit for static array +fail_compilation/fail19890a.d(8): Error: `void[cast(size_t)4294967295]` size 1 * 4294967295 exceeds 0x7fffffff size limit for static array --- */ diff --git a/tests/dmd/fail_compilation/fail19890b.d b/tests/dmd/fail_compilation/fail19890b.d index 19081d95871..f9cfb45d533 100644 --- a/tests/dmd/fail_compilation/fail19890b.d +++ b/tests/dmd/fail_compilation/fail19890b.d @@ -1,7 +1,7 @@ -/* +/* REQUIRED_ARGS: -m32 TEST_OUTPUT: --- -fail_compilation/fail19890b.d(8): Error: `void[$n$$?:64=LU$]` size 1 * $n$ exceeds $?:windows+32omf=0x1000000|0x7fffffff$ size limit for static array +fail_compilation/fail19890b.d(8): Error: `void[cast(size_t)4294967294]` size 1 * 4294967294 exceeds 0x7fffffff size limit for static array --- */ diff --git a/tests/dmd/fail_compilation/fail4611.d b/tests/dmd/fail_compilation/fail4611.d index 04adf13f5e7..259a6da847d 100644 --- a/tests/dmd/fail_compilation/fail4611.d +++ b/tests/dmd/fail_compilation/fail4611.d @@ -1,7 +1,7 @@ -/* +/* REQUIRED_ARGS: -m32 TEST_OUTPUT: --- -fail_compilation/fail4611.d(15): Error: `Vec[$n$]` size 4 * $n$ exceeds $?:windows+32omf=0x1000000|0x7fffffff$ size limit for static array +fail_compilation/fail4611.d(15): Error: `Vec[cast(size_t)2147483647]` size 4 * 2147483647 exceeds 0x7fffffff size limit for static array --- */ diff --git a/tests/dmd/fail_compilation/staticarrayoverflow.d b/tests/dmd/fail_compilation/staticarrayoverflow.d index 1305bc55351..028f8e12487 100644 --- a/tests/dmd/fail_compilation/staticarrayoverflow.d +++ b/tests/dmd/fail_compilation/staticarrayoverflow.d @@ -2,13 +2,13 @@ REQUIRED_ARGS: -m64 TEST_OUTPUT: --- -fail_compilation/staticarrayoverflow.d(23): Error: static array `S[1879048192]` size overflowed to 7516192768000 +fail_compilation/staticarrayoverflow.d(23): Error: static array `S[cast(size_t)1879048192]` size overflowed to 7516192768000 fail_compilation/staticarrayoverflow.d(23): Error: variable `staticarrayoverflow.y` size overflow -fail_compilation/staticarrayoverflow.d(25): Error: static array `S[8070450532247928832]` size overflowed to 8070450532247928832 +fail_compilation/staticarrayoverflow.d(25): Error: static array `S[cast(size_t)8070450532247928832]` size overflowed to 8070450532247928832 fail_compilation/staticarrayoverflow.d(25): Error: variable `staticarrayoverflow.a` size overflow fail_compilation/staticarrayoverflow.d(26): Error: static array `S[0][18446744073709551615LU]` size overflowed to 18446744073709551615 fail_compilation/staticarrayoverflow.d(26): Error: variable `staticarrayoverflow.b` size overflow -fail_compilation/staticarrayoverflow.d(27): Error: static array `S[0][4294967295]` size overflowed to 4294967295 +fail_compilation/staticarrayoverflow.d(27): Error: static array `S[0][cast(size_t)4294967295]` size overflowed to 4294967295 fail_compilation/staticarrayoverflow.d(27): Error: variable `staticarrayoverflow.c` size overflow --- */ From 0a918dc9804d4012505530b52a296137cbfbac32 Mon Sep 17 00:00:00 2001 From: Nicholas Wilson Date: Sat, 23 Dec 2023 17:59:01 +0800 Subject: [PATCH 152/215] Fix typo in assert in `common/smallbuffer.d` --- dmd/common/smallbuffer.d | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dmd/common/smallbuffer.d b/dmd/common/smallbuffer.d index ec0eaae647f..83b67cdbb3d 100644 --- a/dmd/common/smallbuffer.d +++ b/dmd/common/smallbuffer.d @@ -48,7 +48,7 @@ struct SmallBuffer(Element) } else { - assert(len < sizeof.max / (2 * Element.sizeof)); + assert(len < size_t.max / (2 * Element.sizeof)); _extent = (cast(typeof(_extent.ptr)) malloc(len * Element.sizeof))[0 .. len]; _extent.ptr || assert(0, "Out of memory."); needsFree = true; @@ -76,7 +76,7 @@ struct SmallBuffer(Element) else { __dtor(); - assert(len < sizeof.max / Element.sizeof); + assert(len < size_t.max / Element.sizeof); _extent = (cast(typeof(_extent.ptr)) malloc(len * Element.sizeof))[0 .. len]; _extent.ptr || assert(0, "Out of memory."); needsFree = true; From b014c7757fd94ae1e32b084b5e04c1f7221306df Mon Sep 17 00:00:00 2001 From: Dennis Korpel Date: Sun, 24 Dec 2023 00:17:33 +0100 Subject: [PATCH 153/215] Remove deprecated rndtonl from core.math --- runtime/druntime/src/core/math.d | 9 --------- 1 file changed, 9 deletions(-) diff --git a/runtime/druntime/src/core/math.d b/runtime/druntime/src/core/math.d index 30fc1308e4b..941b5de3c4e 100644 --- a/runtime/druntime/src/core/math.d +++ b/runtime/druntime/src/core/math.d @@ -30,15 +30,6 @@ public: nothrow: @safe: -/***************************************** - * Returns x rounded to a long value using the FE_TONEAREST rounding mode. - * If the integer value of x is - * greater than long.max, the result is - * indeterminate. - */ -deprecated("rndtonl is to be removed by 2.100. Please use round instead") -extern (C) real rndtonl(real x); - pure: /*********************************** * Returns cosine of x. x is in radians. From c329a62958045404e35a7785e388b50be8225dbe Mon Sep 17 00:00:00 2001 From: Walter Bright Date: Sat, 23 Dec 2023 17:44:07 -0800 Subject: [PATCH 154/215] hdrgen.d: replace some toChars() with toString() --- dmd/hdrgen.d | 41 +++++++++++++++++++++++++++-------------- 1 file changed, 27 insertions(+), 14 deletions(-) diff --git a/dmd/hdrgen.d b/dmd/hdrgen.d index 6ad9c8f849d..99c4c37ea38 100644 --- a/dmd/hdrgen.d +++ b/dmd/hdrgen.d @@ -944,7 +944,8 @@ void toCBuffer(Dsymbol s, ref OutBuffer buf, ref HdrGenState hgs) } foreach (const pid; imp.packages) { - buf.printf("%s.", pid.toChars()); + buf.write(pid.toString()); + buf.writeByte('.'); } buf.writestring(imp.id.toString()); if (imp.names.length) @@ -1073,7 +1074,9 @@ void toCBuffer(Dsymbol s, ref OutBuffer buf, ref HdrGenState hgs) { if (i) buf.writeByte(' '); - buf.printf("align (%s)", exp.toChars()); + buf.writestring("align ("); + toCBuffer(exp, buf, hgs); + buf.writeByte(')'); } if (d.decl && d.decl.length < 2) buf.writeByte(' '); @@ -1500,7 +1503,7 @@ void toCBuffer(Dsymbol s, ref OutBuffer buf, ref HdrGenState hgs) buf.writestring("mixin "); typeToBuffer(tm.tqual, null, buf, hgs); tiargsToBuffer(tm, buf, hgs); - if (tm.ident && memcmp(tm.ident.toChars(), cast(const(char)*)"__mixin", 7) != 0) + if (tm.ident && memcmp(tm.ident.toString().ptr, cast(const(char)*) "__mixin", 7) != 0) { buf.writeByte(' '); buf.writestring(tm.ident.toString()); @@ -2082,7 +2085,8 @@ private void expressionPrettyPrint(Expression e, ref OutBuffer buf, ref HdrGenSt { if ((cast(EnumMember)em).value.toInteger == v) { - buf.printf("%s.%s", sym.toChars(), em.ident.toChars()); + const id = em.ident.toString(); + buf.printf("%s.%.*s", sym.toChars(), cast(int)id.length, id.ptr); return ; } } @@ -2142,7 +2146,11 @@ private void expressionPrettyPrint(Expression e, ref OutBuffer buf, ref HdrGenSt break; case Tpointer: buf.writestring("cast("); - buf.writestring(t.toChars()); + + HdrGenState hgs2; // should re-examine need for new hgs + hgs2.fullQual = (t.ty == Tclass && !t.mod); + toCBuffer(t, buf, null, hgs2); + buf.writestring(")cast(size_t)"); goto case Tuns64; @@ -3438,14 +3446,15 @@ private void parameterToBuffer(Parameter p, ref OutBuffer buf, ref HdrGenState h STC.return_ | STC.returninferred | STC.scope_ | STC.scopeinferred | STC.out_ | STC.ref_ | STC.returnScope))) buf.writeByte(' '); + const(char)[] s; if (p.storageClass & STC.alias_) { if (p.ident) buf.writestring(p.ident.toString()); } - else if (p.type.ty == Tident && - (cast(TypeIdentifier)p.type).ident.toString().length > 3 && - strncmp((cast(TypeIdentifier)p.type).ident.toChars(), "__T", 3) == 0) + else if (p.type.isTypeIdentifier() && + (s = p.type.isTypeIdentifier().ident.toString()).length > 3 && + s[0..3] == "__T") { // print parameter name, instead of undetermined type parameter buf.writestring(p.ident.toString()); @@ -3686,7 +3695,9 @@ private void tiargsToBuffer(TemplateInstance ti, ref OutBuffer buf, ref HdrGenSt { if (t.equals(Type.tstring) || t.equals(Type.twstring) || t.equals(Type.tdstring) || t.mod == 0 && (t.isTypeBasic() || t.ty == Tident && (cast(TypeIdentifier)t).idents.length == 0)) { - buf.writestring(t.toChars()); + HdrGenState hgs2; // re-examine need for new hgs + hgs2.fullQual = (t.ty == Tclass && !t.mod); + toCBuffer(t, buf, null, hgs2); return; } } @@ -3694,7 +3705,7 @@ private void tiargsToBuffer(TemplateInstance ti, ref OutBuffer buf, ref HdrGenSt { if (e.op == EXP.int64 || e.op == EXP.float64 || e.op == EXP.null_ || e.op == EXP.string_ || e.op == EXP.this_) { - buf.writestring(e.toChars()); + toCBuffer(e, buf, hgs); return; } } @@ -3736,8 +3747,10 @@ private void objectToBuffer(RootObject oarg, ref OutBuffer buf, ref HdrGenState } else if (Dsymbol s = isDsymbol(oarg)) { - const p = s.ident ? s.ident.toChars() : s.toChars(); - buf.writestring(p); + if (s.ident) + buf.writestring(s.ident.toString()); + else + buf.writestring(s.toChars()); } else if (auto v = isTuple(oarg)) { @@ -4166,13 +4179,13 @@ private void typeToBufferx(Type t, ref OutBuffer buf, ref HdrGenState hgs) buf.writestring("const "); if (hgs.importcHdr && t.id) { - buf.writestring(t.id.toChars()); + buf.writestring(t.id.toString()); return; } buf.writestring(Token.toChars(t.tok)); buf.writeByte(' '); if (t.id) - buf.writestring(t.id.toChars()); + buf.writestring(t.id.toString()); if (t.tok == TOK.enum_ && t.base && t.base.ty != TY.Tint32) { buf.writestring(" : "); From f5fdc607f1cb0d1049d917aa874ae7815bf430f9 Mon Sep 17 00:00:00 2001 From: Walter Bright Date: Sat, 23 Dec 2023 18:31:24 -0800 Subject: [PATCH 155/215] add toString to tokens.d --- dmd/tokens.d | 152 ++++++++++++++++++++++++++++----------------------- 1 file changed, 84 insertions(+), 68 deletions(-) diff --git a/dmd/tokens.d b/dmd/tokens.d index 317a6e6c382..e04fc307073 100644 --- a/dmd/tokens.d +++ b/dmd/tokens.d @@ -947,93 +947,111 @@ nothrow: } extern (C++) const(char)* toChars() const + { + return toString().ptr; + } + + /********************************* + * Returns: + * a zero-terminated string representation of the token, + * sometimes reusing a static buffer, sometimes leaking memory + */ + extern (D) const(char)[] toString() const { const bufflen = 3 + 3 * floatvalue.sizeof + 1; - __gshared char[bufflen] buffer; - const(char)* p = &buffer[0]; + __gshared char[bufflen + 2] buffer; // extra 2 for suffixes + char* p = &buffer[0]; switch (value) { case TOK.int32Literal: - snprintf(&buffer[0], bufflen, "%d", cast(int)intvalue); - break; + const length = snprintf(p, bufflen, "%d", cast(int)intvalue); + return p[0 .. length]; + case TOK.uns32Literal: case TOK.wchar_tLiteral: - snprintf(&buffer[0], bufflen, "%uU", cast(uint)unsvalue); - break; + const length = snprintf(p, bufflen, "%uU", cast(uint)unsvalue); + return p[0 .. length]; + case TOK.wcharLiteral: case TOK.dcharLiteral: case TOK.charLiteral: - { - OutBuffer buf; - buf.writeSingleCharLiteral(cast(dchar) intvalue); - buf.writeByte('\0'); - p = buf.extractChars(); - } - break; + OutBuffer buf; + buf.writeSingleCharLiteral(cast(dchar) intvalue); + return buf.extractSlice(true); + case TOK.int64Literal: - snprintf(&buffer[0], bufflen, "%lldL", cast(long)intvalue); - break; + const length = snprintf(p, bufflen, "%lldL", cast(long)intvalue); + return p[0 .. length]; + case TOK.uns64Literal: - snprintf(&buffer[0], bufflen, "%lluUL", cast(ulong)unsvalue); - break; + const length = snprintf(p, bufflen, "%lluUL", cast(ulong)unsvalue); + return p[0 .. length]; + case TOK.float32Literal: - CTFloat.sprint(&buffer[0], bufflen, 'g', floatvalue); - strcat(&buffer[0], "f"); - break; + const length = CTFloat.sprint(p, bufflen, 'g', floatvalue); + p[length] = 'f'; + p[length + 1] = 0; + return p[0 .. length + 1]; + case TOK.float64Literal: - CTFloat.sprint(&buffer[0], bufflen, 'g', floatvalue); - break; + const length = CTFloat.sprint(p, bufflen, 'g', floatvalue); + return p[0 .. length]; + case TOK.float80Literal: - CTFloat.sprint(&buffer[0], bufflen, 'g', floatvalue); - strcat(&buffer[0], "L"); - break; + const length = CTFloat.sprint(p, bufflen, 'g', floatvalue); + p[length] = 'L'; + p[length + 1] = 0; + return p[0 .. length + 1]; + case TOK.imaginary32Literal: - CTFloat.sprint(&buffer[0], bufflen, 'g', floatvalue); - strcat(&buffer[0], "fi"); - break; + const length = CTFloat.sprint(p, bufflen, 'g', floatvalue); + p[length ] = 'f'; + p[length + 1] = 'i'; + p[length + 2] = 0; + return p[0 .. length + 2]; + case TOK.imaginary64Literal: - CTFloat.sprint(&buffer[0], bufflen, 'g', floatvalue); - strcat(&buffer[0], "i"); - break; + const length = CTFloat.sprint(p, bufflen, 'g', floatvalue); + p[length] = 'i'; + p[length + 1] = 0; + return p[0 .. length + 1]; + case TOK.imaginary80Literal: - CTFloat.sprint(&buffer[0], bufflen, 'g', floatvalue); - strcat(&buffer[0], "Li"); - break; + const length = CTFloat.sprint(p, bufflen, 'g', floatvalue); + p[length ] = 'L'; + p[length + 1] = 'i'; + p[length + 2] = 0; + return p[0 .. length + 2]; + case TOK.string_: + OutBuffer buf; + buf.writeByte('"'); + for (size_t i = 0; i < len;) { - OutBuffer buf; - buf.writeByte('"'); - for (size_t i = 0; i < len;) - { - dchar c; - utf_decodeChar(ustring[0 .. len], i, c); - writeCharLiteral(buf, c); - } - buf.writeByte('"'); - if (postfix) - buf.writeByte(postfix); - buf.writeByte(0); - p = buf.extractChars(); + dchar c; + utf_decodeChar(ustring[0 .. len], i, c); + writeCharLiteral(buf, c); } - break; + buf.writeByte('"'); + if (postfix) + buf.writeByte(postfix); + return buf.extractSlice(true); + case TOK.hexadecimalString: + OutBuffer buf; + buf.writeByte('x'); + buf.writeByte('"'); + foreach (size_t i; 0 .. len) { - 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.extractData(); - break; + if (i) + buf.writeByte(' '); + buf.printf("%02x", ustring[i]); } + buf.writeByte('"'); + if (postfix) + buf.writeByte(postfix); + return buf.extractSlice(true); + case TOK.identifier: case TOK.enum_: case TOK.struct_: @@ -1062,13 +1080,11 @@ nothrow: case TOK.complex64: case TOK.complex80: case TOK.void_: - p = ident.toChars(); - break; + return ident.toString(); + default: - p = toChars(value); - break; + return tochars[value]; } - return p; } static const(char)* toChars(TOK value) From 16b979b75928d5beb93e6e6567969d9f50b4e802 Mon Sep 17 00:00:00 2001 From: Walter Bright Date: Sat, 23 Dec 2023 21:31:36 -0800 Subject: [PATCH 156/215] hdrgen.d: more conversion to toString() (dlang/dmd!15952) --- dmd/hdrgen.d | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/dmd/hdrgen.d b/dmd/hdrgen.d index 99c4c37ea38..2eef70d6ce6 100644 --- a/dmd/hdrgen.d +++ b/dmd/hdrgen.d @@ -826,7 +826,7 @@ private void statementToBuffer(Statement s, ref OutBuffer buf, ref HdrGenState h buf.level++; while (t) { - buf.writestring(t.toChars()); + buf.writestring(t.toString()); if (t.next && t.value != TOK.min && t.value != TOK.comma && t.next.value != TOK.comma && @@ -2468,7 +2468,10 @@ private void expressionPrettyPrint(Expression e, ref OutBuffer buf, ref HdrGenSt typeToBuffer(e.targ, e.id, buf, hgs); if (e.tok2 != TOK.reserved) { - buf.printf(" %s %s", Token.toChars(e.tok), Token.toChars(e.tok2)); + buf.writeByte(' '); + buf.writestring(Token.toString(e.tok)); + buf.writeByte(' '); + buf.writestring(Token.toString(e.tok2)); } else if (e.tspec) { @@ -4182,7 +4185,7 @@ private void typeToBufferx(Type t, ref OutBuffer buf, ref HdrGenState hgs) buf.writestring(t.id.toString()); return; } - buf.writestring(Token.toChars(t.tok)); + buf.writestring(Token.toString(t.tok)); buf.writeByte(' '); if (t.id) buf.writestring(t.id.toString()); From 67b4f59e4c89eee85037d432932610de74a04e6b Mon Sep 17 00:00:00 2001 From: Paul Backus Date: Mon, 25 Dec 2023 14:43:52 -0500 Subject: [PATCH 157/215] Fix 24301 - Misleading error message when passing non-copyable struct by value in @safe code If a copy constructor is explicitly marked with @disable, the error message should mention that, regardless of whether its attributes are allowed in the calling scope. --- dmd/typesem.d | 10 +++++++++- tests/dmd/fail_compilation/fail24301.d | 19 +++++++++++++++++++ 2 files changed, 28 insertions(+), 1 deletion(-) create mode 100644 tests/dmd/fail_compilation/fail24301.d diff --git a/dmd/typesem.d b/dmd/typesem.d index d70f3fd5af8..30bf1dfe6a1 100644 --- a/dmd/typesem.d +++ b/dmd/typesem.d @@ -711,7 +711,15 @@ private extern(D) bool isCopyConstructorCallable (StructDeclaration argStruct, s ~= "@safe "; if (!f.isNogc && sc.func.setGC(arg.loc, null)) s ~= "nogc "; - if (s) + if (f.isDisabled() && !f.isGenerated()) + { + /* https://issues.dlang.org/show_bug.cgi?id=24301 + * Copy constructor is explicitly disabled + */ + buf.printf("`%s` copy constructor cannot be used because it is annotated with `@disable`", + f.type.toChars()); + } + else if (s) { s[$-1] = '\0'; buf.printf("`%s` copy constructor cannot be called from a `%s` context", f.type.toChars(), s.ptr); diff --git a/tests/dmd/fail_compilation/fail24301.d b/tests/dmd/fail_compilation/fail24301.d new file mode 100644 index 00000000000..be09c883e1c --- /dev/null +++ b/tests/dmd/fail_compilation/fail24301.d @@ -0,0 +1,19 @@ +/+ +TEST_OUTPUT: +--- +fail_compilation/fail24301.d(18): Error: function `fail24301.fun(S __param_0)` is not callable using argument types `(S)` +fail_compilation/fail24301.d(18): `ref S(ref S)` copy constructor cannot be used because it is annotated with `@disable` +--- ++/ +struct S +{ + @disable this(ref S); +} + +@safe void fun(S) {} + +@safe void main() +{ + S s; + fun(s); +} From a28266b2905bf0f1f63ef100bb970d05c2377202 Mon Sep 17 00:00:00 2001 From: Walter Bright Date: Tue, 26 Dec 2023 23:18:29 -0800 Subject: [PATCH 158/215] fix Issue 24280 - ImportC: forward reference error when compiling multiple files --- dmd/typesem.d | 13 +++++++++---- tests/dmd/compilable/imports/test24280b.i | 19 +++++++++++++++++++ tests/dmd/compilable/test24280.i | 6 ++++++ 3 files changed, 34 insertions(+), 4 deletions(-) create mode 100644 tests/dmd/compilable/imports/test24280b.i create mode 100644 tests/dmd/compilable/test24280.i diff --git a/dmd/typesem.d b/dmd/typesem.d index 30bf1dfe6a1..4ff8614b631 100644 --- a/dmd/typesem.d +++ b/dmd/typesem.d @@ -2326,11 +2326,16 @@ extern(C++) Type typeSemantic(Type type, const ref Loc loc, Scope* sc) Type visitTag(TypeTag mtype) { //printf("TypeTag.semantic() %s\n", mtype.toChars()); + Type returnType(Type t) + { + return t.deco ? t : t.merge(); + } + if (mtype.resolved) { /* struct S s, *p; */ - return mtype.resolved.addSTC(mtype.mod); + return returnType(mtype.resolved.addSTC(mtype.mod)); } /* Find the current scope by skipping tag scopes. @@ -2403,7 +2408,7 @@ extern(C++) Type typeSemantic(Type type, const ref Loc loc, Scope* sc) { mtype.id = Identifier.generateId("__tag"[]); declareTag(); - return mtype.resolved.addSTC(mtype.mod); + return returnType(mtype.resolved.addSTC(mtype.mod)); } /* look for pre-existing declaration @@ -2416,7 +2421,7 @@ extern(C++) Type typeSemantic(Type type, const ref Loc loc, Scope* sc) if (mtype.tok == TOK.enum_ && !mtype.members) .error(mtype.loc, "`enum %s` is incomplete without members", mtype.id.toChars()); // C11 6.7.2.3-3 declareTag(); - return mtype.resolved.addSTC(mtype.mod); + return returnType(mtype.resolved.addSTC(mtype.mod)); } /* A redeclaration only happens if both declarations are in @@ -2516,7 +2521,7 @@ extern(C++) Type typeSemantic(Type type, const ref Loc loc, Scope* sc) declareTag(); } } - return mtype.resolved.addSTC(mtype.mod); + return returnType(mtype.resolved.addSTC(mtype.mod)); } switch (type.ty) diff --git a/tests/dmd/compilable/imports/test24280b.i b/tests/dmd/compilable/imports/test24280b.i new file mode 100644 index 00000000000..bdabef8134e --- /dev/null +++ b/tests/dmd/compilable/imports/test24280b.i @@ -0,0 +1,19 @@ +struct S; + +struct timespec +{ + int s; +}; + +typedef struct timespec Clock; + +Clock now() +{ + Clock result; + return result; +} + +struct S +{ + Clock clock; +}; diff --git a/tests/dmd/compilable/test24280.i b/tests/dmd/compilable/test24280.i new file mode 100644 index 00000000000..e761c4b93cd --- /dev/null +++ b/tests/dmd/compilable/test24280.i @@ -0,0 +1,6 @@ +// EXTRA_SOURCES: imports/test24280b.i + +struct timespec +{ + int s; +}; From 7375f7185b3e8e965d4eebf8e6e5d63d666bb4e0 Mon Sep 17 00:00:00 2001 From: Mathias Lang Date: Wed, 27 Dec 2023 15:57:32 +0100 Subject: [PATCH 159/215] Trivial: Use REQUIRED_ARGS instead of PERMUTE_ARGS for preview=in test If the mangling was to change, this test would fail. There is no reason to use PERMUTE_ARGS here, and so it's better to use the more restrictive REQUIRED_ARGS. --- tests/dmd/fail_compilation/diagin.d | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/dmd/fail_compilation/diagin.d b/tests/dmd/fail_compilation/diagin.d index 1748e92a841..5b8e33162cd 100644 --- a/tests/dmd/fail_compilation/diagin.d +++ b/tests/dmd/fail_compilation/diagin.d @@ -1,5 +1,5 @@ /* -PERMUTE_ARGS: -preview=in +REQUIRED_ARGS: -preview=in TEST_OUTPUT: --- fail_compilation/diagin.d(14): Error: function `diagin.foo(in int)` is not callable using argument types `()` From acd410ffa7eb0d98d4fd7dc71a5c4ec6be46c172 Mon Sep 17 00:00:00 2001 From: Walter Bright Date: Wed, 27 Dec 2023 13:22:50 -0800 Subject: [PATCH 160/215] fix Issue 24297 - ImportC incompatible with glibc _FORTIFY_SOURCE (dlang/dmd!15957) --- runtime/druntime/src/importc.h | 1 + 1 file changed, 1 insertion(+) diff --git a/runtime/druntime/src/importc.h b/runtime/druntime/src/importc.h index ee80be8177c..a56455c5882 100644 --- a/runtime/druntime/src/importc.h +++ b/runtime/druntime/src/importc.h @@ -33,6 +33,7 @@ #define __attribute __attribute__ #define __alignof _Alignof #define __vector_size__ vector_size +#define __typeof typeof /******************** * Clang nullability extension used by macOS headers. From d2238d163c21cc29cf0eb165bd1af6ea126da9d2 Mon Sep 17 00:00:00 2001 From: Walter Bright Date: Wed, 27 Dec 2023 13:48:28 -0800 Subject: [PATCH 161/215] fix Issue 24304 - __uint16_t, __uint32_t, __uint64_t are not recognized (dlang/dmd!15956) --- runtime/druntime/src/importc.h | 5 +++++ tests/dmd/compilable/test23214.c | 10 ++++++++++ 2 files changed, 15 insertions(+) diff --git a/runtime/druntime/src/importc.h b/runtime/druntime/src/importc.h index a56455c5882..815723ef819 100644 --- a/runtime/druntime/src/importc.h +++ b/runtime/druntime/src/importc.h @@ -61,6 +61,11 @@ #define __int32 int #define __int64 long long +/* Linux builtin types */ +typedef unsigned short __uint16_t; +typedef unsigned int __uint32_t; +typedef unsigned long long __uint64_t; + /********************* * Obsolete detritus */ diff --git a/tests/dmd/compilable/test23214.c b/tests/dmd/compilable/test23214.c index 9aa38bef542..b5b83b66d46 100644 --- a/tests/dmd/compilable/test23214.c +++ b/tests/dmd/compilable/test23214.c @@ -1,3 +1,13 @@ // https://issues.dlang.org/show_bug.cgi?id=23214 typedef unsigned __int64 uintptr_t; + +// https://issues.dlang.org/show_bug.cgi?id=24304 + +__uint16_t u16; +__uint32_t u32; +__uint64_t u64; + +_Static_assert(sizeof(u16) == 2, "1"); +_Static_assert(sizeof(u32) == 4, "2"); +_Static_assert(sizeof(u64) == 8, "3"); From 136abdeee396629f973bc188c30f11b1319556aa Mon Sep 17 00:00:00 2001 From: "richard (rikki) andrew cattermole" Date: Fri, 29 Dec 2023 08:17:30 +1300 Subject: [PATCH 162/215] Remove wrongly const parameters from stdatomic functions --- runtime/druntime/src/core/stdc/stdatomic.d | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/runtime/druntime/src/core/stdc/stdatomic.d b/runtime/druntime/src/core/stdc/stdatomic.d index 6ea47a3189f..926e1f54463 100644 --- a/runtime/druntime/src/core/stdc/stdatomic.d +++ b/runtime/druntime/src/core/stdc/stdatomic.d @@ -513,7 +513,7 @@ unittest /// pragma(inline, true) -A atomic_exchange_impl(A, C)(const shared(A)* obj, C desired) @trusted +A atomic_exchange_impl(A, C)(shared(A)* obj, C desired) @trusted { assert(obj !is null); return atomicExchange(cast(shared(A)*)obj, cast(A)desired); @@ -528,7 +528,7 @@ unittest /// pragma(inline, true) -A atomic_exchange_explicit_impl(A, C)(const shared(A)* obj, C desired, memory_order order) @trusted +A atomic_exchange_explicit_impl(A, C)(shared(A)* obj, C desired, memory_order order) @trusted { assert(obj !is null); From e6811bda71ee680b55e20bac24e9e998506cc5c9 Mon Sep 17 00:00:00 2001 From: Tim Schendekehl Date: Thu, 28 Dec 2023 19:27:05 +0100 Subject: [PATCH 163/215] Fix issue 22905 - gdb backtrace contains wrong location The default argument for function funcC in the example is wrapped in an implicit cast expression. The location for this expression was not changed to the call site, because the visit function returned earlier for unary expressions. Now the location is changed for every type of expression. --- dmd/expressionsem.d | 3 ++- tests/dmd/runnable/gdb22905.d | 20 ++++++++++++++++++++ tests/dmd/runnable/imports/gdb22905b.d | 8 ++++++++ tests/dmd/runnable/imports/gdb22905c.d | 13 +++++++++++++ 4 files changed, 43 insertions(+), 1 deletion(-) create mode 100644 tests/dmd/runnable/gdb22905.d create mode 100644 tests/dmd/runnable/imports/gdb22905b.d create mode 100644 tests/dmd/runnable/imports/gdb22905c.d diff --git a/dmd/expressionsem.d b/dmd/expressionsem.d index c21b382c71e..13c9ceea485 100644 --- a/dmd/expressionsem.d +++ b/dmd/expressionsem.d @@ -15037,6 +15037,8 @@ bool checkSharedAccess(Expression e, Scope* sc, bool returnRef = false) */ Expression resolveLoc(Expression exp, const ref Loc loc, Scope* sc) { + exp.loc = loc; + Expression visit(Expression exp) { if (auto unaExp = exp.isUnaExp()) @@ -15044,7 +15046,6 @@ Expression resolveLoc(Expression exp, const ref Loc loc, Scope* sc) unaExp.e1 = unaExp.e1.resolveLoc(loc, sc); return unaExp; } - exp.loc = loc; return exp; } diff --git a/tests/dmd/runnable/gdb22905.d b/tests/dmd/runnable/gdb22905.d new file mode 100644 index 00000000000..842f61414b1 --- /dev/null +++ b/tests/dmd/runnable/gdb22905.d @@ -0,0 +1,20 @@ +/* +EXTRA_SOURCES: imports/gdb22905b.d imports/gdb22905c.d +REQUIRED_ARGS: -g +GDB_SCRIPT: +--- +b gdb22905c.d:6 +commands +bt +cont +end +run +--- +GDB_MATCH: _D7imports9gdb22905b5funcBFZv .. at runnable/imports/gdb22905b.d:7 +*/ +import imports.gdb22905b; + +void main() +{ + funcB(); +} diff --git a/tests/dmd/runnable/imports/gdb22905b.d b/tests/dmd/runnable/imports/gdb22905b.d new file mode 100644 index 00000000000..77cd1189666 --- /dev/null +++ b/tests/dmd/runnable/imports/gdb22905b.d @@ -0,0 +1,8 @@ +module imports.gdb22905b; +import imports.gdb22905c; + +pragma(inline, false) +void funcB() +{ + funcC(0); +} diff --git a/tests/dmd/runnable/imports/gdb22905c.d b/tests/dmd/runnable/imports/gdb22905c.d new file mode 100644 index 00000000000..eb26308659c --- /dev/null +++ b/tests/dmd/runnable/imports/gdb22905c.d @@ -0,0 +1,13 @@ +module imports.gdb22905c; + +pragma(inline, false) +void funcC(T)(T param, void delegate() dg = null) +{ + return; +} + +struct S +{ + void function() f; + void *ptr; +} From 02b8e2fe87815d9e46eadef9a122f1b29aabd2e6 Mon Sep 17 00:00:00 2001 From: Walter Bright Date: Thu, 28 Dec 2023 19:55:42 -0800 Subject: [PATCH 164/215] fix Issue 24303 - anonymous struct problems when typedef'd in separate C files (dlang/dmd!15958) --- dmd/cparse.d | 18 ++++++++---------- tests/dmd/compilable/imports/test24280b.i | 14 ++++++++++++++ tests/dmd/compilable/test24280.i | 14 ++++++++++++++ 3 files changed, 36 insertions(+), 10 deletions(-) diff --git a/dmd/cparse.d b/dmd/cparse.d index 4c0b96a4c8c..f67989b9bb1 100644 --- a/dmd/cparse.d +++ b/dmd/cparse.d @@ -1931,20 +1931,18 @@ final class CParser(AST) : Parser!AST } else if (auto tt = dt.isTypeTag()) { - if (tt.id || tt.tok == TOK.enum_) - { - if (!tt.id && id) - /* This applies for enums declared as - * typedef enum {A} E; - */ - tt.id = id; - Specifier spec; - declareTag(tt, spec); - } + if (!tt.id && id) + /* This applies for enums declared as + * typedef enum {A} E; + */ + tt.id = id; + Specifier spec; + declareTag(tt, spec); idt = tt.id; } if (isalias) { + //printf("AliasDeclaration %s %s\n", id.toChars(), dt.toChars()); auto ad = new AST.AliasDeclaration(token.loc, id, dt); if (id == idt) ad.adFlags |= ad.hidden; // do not print when generating .di files diff --git a/tests/dmd/compilable/imports/test24280b.i b/tests/dmd/compilable/imports/test24280b.i index bdabef8134e..5c3edf21fce 100644 --- a/tests/dmd/compilable/imports/test24280b.i +++ b/tests/dmd/compilable/imports/test24280b.i @@ -17,3 +17,17 @@ struct S { Clock clock; }; + +/* https://issues.dlang.org/show_bug.cgi?id=24303 */ + +typedef struct {} Slice; + +struct Lang +{ + Slice *slices; +}; + +void langmap(struct Lang *self) +{ + Slice slice = *self->slices; +} diff --git a/tests/dmd/compilable/test24280.i b/tests/dmd/compilable/test24280.i index e761c4b93cd..0a6aa0a27c0 100644 --- a/tests/dmd/compilable/test24280.i +++ b/tests/dmd/compilable/test24280.i @@ -4,3 +4,17 @@ struct timespec { int s; }; + +/* https://issues.dlang.org/show_bug.cgi?id=24303 */ + +typedef struct {} Slice; + +struct Lang +{ + Slice *slices; +}; + +void langmap(struct Lang *self) +{ + Slice slice = *self->slices; +} From 12c6cd159bbcb6fa09c31beb92f01a8c089824b8 Mon Sep 17 00:00:00 2001 From: Nick Treleaven Date: Fri, 29 Dec 2023 17:10:55 +0000 Subject: [PATCH 165/215] Deprecate string literals as (static) assert conditions (dlang/dmd!15860) * Deprecate string literals as assert conditions Fix Issue 14387 - Disallow string literals as assert conditions * Avoid running expression semantic, only deprecate literals Ignore enum strings. * Fix runnable test --- dmd/expressionsem.d | 7 +++++++ dmd/semantic2.d | 7 +++++++ tests/dmd/fail_compilation/array_bool.d | 22 ++++++++++++++++++++++ tests/dmd/runnable/testpdb.d | 2 +- 4 files changed, 37 insertions(+), 1 deletion(-) create mode 100644 tests/dmd/fail_compilation/array_bool.d diff --git a/dmd/expressionsem.d b/dmd/expressionsem.d index 13c9ceea485..8a01644d141 100644 --- a/dmd/expressionsem.d +++ b/dmd/expressionsem.d @@ -7592,6 +7592,13 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor { printf("AssertExp::semantic('%s')\n", exp.toChars()); } + if (auto e = exp.e1.isStringExp()) + { + // deprecated in 2.107 + deprecation(e.loc, "assert condition cannot be a string literal"); + deprecationSupplemental(e.loc, "If intentional, use `%s !is null` instead to preserve behaviour", + e.toChars()); + } const generateMsg = !exp.msg && sc.needsCodegen() && // let ctfe interpreter handle the error message diff --git a/dmd/semantic2.d b/dmd/semantic2.d index 036560b5407..292cf62c59c 100644 --- a/dmd/semantic2.d +++ b/dmd/semantic2.d @@ -93,6 +93,13 @@ private extern(C++) final class Semantic2Visitor : Visitor override void visit(StaticAssert sa) { //printf("StaticAssert::semantic2() %s\n", sa.toChars()); + if (const e = sa.exp.isStringExp()) + { + // deprecated in 2.107 + deprecation(e.loc, "static assert condition cannot be a string literal"); + deprecationSupplemental(e.loc, "If intentional, use `%s !is null` instead to preserve behaviour", + e.toChars()); + } auto sds = new ScopeDsymbol(); sc = sc.push(sds); sc.tinst = null; diff --git a/tests/dmd/fail_compilation/array_bool.d b/tests/dmd/fail_compilation/array_bool.d new file mode 100644 index 00000000000..923766a93fe --- /dev/null +++ b/tests/dmd/fail_compilation/array_bool.d @@ -0,0 +1,22 @@ +/* +REQUIRED_ARGS: -de +TEST_OUTPUT: +--- +fail_compilation/array_bool.d(13): Deprecation: assert condition cannot be a string literal +fail_compilation/array_bool.d(13): If intentional, use `"foo" !is null` instead to preserve behaviour +fail_compilation/array_bool.d(14): Deprecation: static assert condition cannot be a string literal +fail_compilation/array_bool.d(14): If intentional, use `"foo" !is null` instead to preserve behaviour +--- +*/ +void main() +{ + assert("foo"); + static assert("foo"); + + assert("foo".ptr); // OK + static assert("foo".ptr); // OK + + enum e = "bar"; + static assert(e); // OK + assert(e); // OK +} diff --git a/tests/dmd/runnable/testpdb.d b/tests/dmd/runnable/testpdb.d index 55207c708e7..8a1b10dfb96 100644 --- a/tests/dmd/runnable/testpdb.d +++ b/tests/dmd/runnable/testpdb.d @@ -1087,7 +1087,7 @@ bool openDebugInfo(IDiaDataSource* source, IDiaSession* session, IDiaSymbol* glo { wchar[MAX_PATH] exepath; DWORD len = GetModuleFileNameW(null, exepath.ptr, MAX_PATH); - len < MAX_PATH || assert("executable path too long"); + len < MAX_PATH || assert(false, "executable path too long"); HRESULT hr = CoInitialize(NULL); From 24f81aa9924a8585d654b2382ed5ded349427023 Mon Sep 17 00:00:00 2001 From: Walter Bright Date: Fri, 29 Dec 2023 17:01:45 -0800 Subject: [PATCH 166/215] fix Issue 24306 - ImportC: same name structs in separate C files interfere when compiled together --- dmd/dsymbolsem.d | 8 +++++++- tests/dmd/compilable/imports/test24280b.i | 4 ++++ tests/dmd/compilable/test24280.i | 4 ++++ 3 files changed, 15 insertions(+), 1 deletion(-) diff --git a/dmd/dsymbolsem.d b/dmd/dsymbolsem.d index a015fb39224..62f3d698a12 100644 --- a/dmd/dsymbolsem.d +++ b/dmd/dsymbolsem.d @@ -4849,9 +4849,15 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor { if (ts.sym != sd) { - auto ti = ts.sym.isInstantiated(); + TemplateInstance ti = ts.sym.isInstantiated(); if (ti && isError(ti)) ts.sym = sd; + /* For C modules, if module A contains `struct S;` and + * module B contains `struct S { members...}` then replace + * the former with the latter + */ + else if (!ts.sym.members && sd.members) + ts.sym = sd; } } diff --git a/tests/dmd/compilable/imports/test24280b.i b/tests/dmd/compilable/imports/test24280b.i index 5c3edf21fce..2b120e2be33 100644 --- a/tests/dmd/compilable/imports/test24280b.i +++ b/tests/dmd/compilable/imports/test24280b.i @@ -31,3 +31,7 @@ void langmap(struct Lang *self) { Slice slice = *self->slices; } + +/* https://issues.dlang.org/show_bug.cgi?id=24306 */ + +struct T { }; diff --git a/tests/dmd/compilable/test24280.i b/tests/dmd/compilable/test24280.i index 0a6aa0a27c0..377e6869861 100644 --- a/tests/dmd/compilable/test24280.i +++ b/tests/dmd/compilable/test24280.i @@ -18,3 +18,7 @@ void langmap(struct Lang *self) { Slice slice = *self->slices; } + +/* https://issues.dlang.org/show_bug.cgi?id=24306 */ + +struct T; From 3d0035845c2ccc612a3635ac8d925ea4a54be62d Mon Sep 17 00:00:00 2001 From: Walter Bright Date: Fri, 29 Dec 2023 21:15:05 -0800 Subject: [PATCH 167/215] ImportC: give error when encountering computed goto --- dmd/cparse.d | 24 ++++++++++++++++++++---- tests/dmd/fail_compilation/compgoto.i | 18 ++++++++++++++++++ 2 files changed, 38 insertions(+), 4 deletions(-) create mode 100644 tests/dmd/fail_compilation/compgoto.i diff --git a/dmd/cparse.d b/dmd/cparse.d index f67989b9bb1..de85593a9e4 100644 --- a/dmd/cparse.d +++ b/dmd/cparse.d @@ -605,15 +605,23 @@ final class CParser(AST) : Parser!AST { Identifier ident; nextToken(); - if (token.value != TOK.identifier) + if (token.value == TOK.identifier) { - error("identifier expected following `goto`"); + ident = token.ident; + nextToken(); + } + else if (token.value == TOK.mul) + { + /* https://gcc.gnu.org/onlinedocs/gcc/Labels-as-Values.html + */ + error("`goto *` computed goto extension is not supported"); ident = null; + cparseUnaryExp(); // parse and throw away } else { - ident = token.ident; - nextToken(); + error("identifier expected following `goto`"); + ident = null; } s = new AST.GotoStatement(loc, ident); check(TOK.semicolon, "`goto` statement"); @@ -1056,6 +1064,14 @@ final class CParser(AST) : Parser!AST break; } + case TOK.andAnd: + /* https://gcc.gnu.org/onlinedocs/gcc/Labels-as-Values.html + */ + error("unary `&&` computed goto extension is not supported"); + nextToken(); + e = cparseCastExp(); + break; + case TOK._Alignof: { nextToken(); diff --git a/tests/dmd/fail_compilation/compgoto.i b/tests/dmd/fail_compilation/compgoto.i new file mode 100644 index 00000000000..6163ffcca60 --- /dev/null +++ b/tests/dmd/fail_compilation/compgoto.i @@ -0,0 +1,18 @@ +/* TEST_OUTPUT: +--- +fail_compilation/compgoto.i(105): Error: unary `&&` computed goto extension is not supported +fail_compilation/compgoto.i(106): Error: `goto *` computed goto extension is not supported +--- + */ + +// https://gcc.gnu.org/onlinedocs/gcc/Labels-as-Values.html + +#line 100 + +void test() +{ + void *ptr; + foo: + ptr = &&foo; + goto *ptr; +} From 5215129013bb44fddb676d2ed73292c67e8af744 Mon Sep 17 00:00:00 2001 From: "richard (rikki) andrew cattermole" Date: Fri, 29 Dec 2023 18:15:36 +1300 Subject: [PATCH 168/215] Implement changes to stdatomic suggested by Iain regarding default memory orders for operations where a memory order isn't valid --- runtime/druntime/src/core/stdc/stdatomic.d | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/runtime/druntime/src/core/stdc/stdatomic.d b/runtime/druntime/src/core/stdc/stdatomic.d index 926e1f54463..ae17e040da7 100644 --- a/runtime/druntime/src/core/stdc/stdatomic.d +++ b/runtime/druntime/src/core/stdc/stdatomic.d @@ -169,9 +169,9 @@ void atomic_flag_clear_explicit_impl()(atomic_flag* obj, memory_order order) break; case memory_order.memory_order_acquire: - // What GCC does here is generate a relaxed order (no barriers) - // we'll copy it, although the D compiler should really be helping out at compile time. - atomicStore!(memory_order.memory_order_relaxed)(&obj.b, false); + // Ideally this would error at compile time but alas it is not an intrinsic. + // Note: this is not a valid memory order for this operation. + atomicStore!(memory_order.memory_order_seq_cst)(&obj.b, false); break; case memory_order.memory_order_release: @@ -436,9 +436,9 @@ void atomic_store_explicit_impl(A, C)(shared(A)* obj, C desired, memory_order or break; case memory_order.memory_order_acquire: - // What GCC does here is generate a relaxed order (no barriers) - // we'll copy it, although the D compiler should really be helping out at compile time. - atomicStore!(memory_order.memory_order_relaxed)(obj, cast(A)desired); + // Ideally this would error at compile time but alas it is not an intrinsic. + // Note: this is not a valid memory order for this operation. + atomicStore!(memory_order.memory_order_release)(obj, cast(A)desired); break; case memory_order.memory_order_release: @@ -492,9 +492,9 @@ A atomic_load_explicit_impl(A)(const shared(A)* obj, memory_order order) @truste return atomicLoad!(memory_order.memory_order_acquire)(obj); case memory_order.memory_order_release: - // What GCC does here is generate a relaxed order (no barriers) - // we'll copy it, although the D compiler should really be helping out at compile time. - return atomicLoad!(memory_order.memory_order_relaxed)(obj); + // Ideally this would error at compile time but alas it is not an intrinsic. + // Note: this is not a valid memory order for this operation. + return atomicLoad!(memory_order.memory_order_acquire)(obj); case memory_order.memory_order_acq_rel: return atomicLoad!(memory_order.memory_order_acq_rel)(obj); From c8944a199e8dffd58bff6744eb9be179c72059fc Mon Sep 17 00:00:00 2001 From: Rainer Schuetze Date: Sat, 30 Dec 2023 22:26:57 +0100 Subject: [PATCH 169/215] fix issue 4071 and others: shared runtime DLL for Windows (dlang/dmd!14849) Allow exporting all generated symbols (including internal symbols). Implement switch `-dllimport` ( windows only, not restricted to `extern(D)`) Still to do: * running shared module ctors * running thread local module ctors * registering DATA/TLS ranges with the GC * exceptions --- dmd/cli.d | 17 +++++++++ dmd/declaration.d | 2 - dmd/declaration.h | 1 - dmd/frontend.h | 1 - dmd/inline.d | 3 -- dmd/mars.d | 38 +++++++++++++++++++ runtime/druntime/Makefile | 18 ++++++--- runtime/druntime/src/rt/msvc.d | 2 + runtime/druntime/src/rt/sections.d | 5 ++- runtime/druntime/test/common.mak | 3 +- runtime/druntime/test/shared/Makefile | 5 ++- .../druntime/test/shared/src/dynamiccast.d | 5 ++- 12 files changed, 82 insertions(+), 18 deletions(-) diff --git a/dmd/cli.d b/dmd/cli.d index a88825786c8..ebfd9504a7f 100644 --- a/dmd/cli.d +++ b/dmd/cli.d @@ -336,6 +336,15 @@ dmd -cov -unittest myprog.d With $(I filename), write module dependencies as text to $(I filename) (only imports).`, ), + Option("dllimport=", + "Windows only: select symbols to dllimport (none/defaultLibsOnly/all)", + `Which global variables to dllimport implicitly if not defined in a root module + $(UL + $(LI $(I none): None) + $(LI $(I defaultLibsOnly): Only druntime/Phobos symbols) + $(LI $(I all): All) + )`, + ), Option("extern-std=", "set C++ name mangling compatibility with ", "Standards supported are: @@ -812,6 +821,14 @@ dmd -cov -unittest myprog.d Option("vgc", "list all gc allocations including hidden ones" ), + Option("visibility=", + "default visibility of symbols (default/hidden/public)", + "$(UL + $(LI $(I default): Hidden for Windows targets without -shared, otherwise public) + $(LI $(I hidden): Only export symbols marked with 'export') + $(LI $(I public): Export all symbols) + )", + ), Option("vtls", "list all variables going into thread local storage" ), diff --git a/dmd/declaration.d b/dmd/declaration.d index bdc91f4f1f2..b357a63663a 100644 --- a/dmd/declaration.d +++ b/dmd/declaration.d @@ -246,8 +246,6 @@ extern (C++) abstract class Declaration : Dsymbol enum nounderscore = 4; // don't prepend _ to mangled name enum hidden = 8; // don't print this in .di files - Symbol* isym; // import version of csym - // overridden symbol with pragma(mangle, "...") const(char)[] mangleOverride; diff --git a/dmd/declaration.h b/dmd/declaration.h index 6b23f70e2bd..484cf9feede 100644 --- a/dmd/declaration.h +++ b/dmd/declaration.h @@ -118,7 +118,6 @@ class Declaration : public Dsymbol LINK _linkage; // may be `LINK::system`; use `resolvedLinkage()` to resolve it 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 override; diff --git a/dmd/frontend.h b/dmd/frontend.h index 6e2bf5ac062..64296ec8262 100644 --- a/dmd/frontend.h +++ b/dmd/frontend.h @@ -6739,7 +6739,6 @@ class Declaration : public Dsymbol enum : int32_t { hidden = 8 }; - Symbol* isym; _d_dynamicArray< const char > mangleOverride; const char* kind() const override; uinteger_t size(const Loc& loc) final override; diff --git a/dmd/inline.d b/dmd/inline.d index e1dac5c69de..4dc87a5565a 100644 --- a/dmd/inline.d +++ b/dmd/inline.d @@ -669,7 +669,6 @@ public: memcpy(cast(void*)vto, cast(void*)vd, __traits(classInstanceSize, VarDeclaration)); vto.parent = ids.parent; vto.csym = null; - vto.isym = null; ids.from.push(vd); ids.to.push(vto); @@ -845,7 +844,6 @@ public: memcpy(cast(void*)vto, cast(void*)vd, __traits(classInstanceSize, VarDeclaration)); vto.parent = ids.parent; vto.csym = null; - vto.isym = null; ids.from.push(vd); ids.to.push(vto); @@ -874,7 +872,6 @@ public: memcpy(cast(void*)vto, cast(void*)vd, __traits(classInstanceSize, VarDeclaration)); vto.parent = ids.parent; vto.csym = null; - vto.isym = null; ids.from.push(vd); ids.to.push(vto); diff --git a/dmd/mars.d b/dmd/mars.d index 6f87beeb383..1aa01e379d2 100644 --- a/dmd/mars.d +++ b/dmd/mars.d @@ -789,6 +789,44 @@ bool parseCommandLine(const ref Strings arguments, const size_t argc, ref Param } else if (arg == "-shared") driverParams.dll = true; + else if (startsWith(p + 1, "visibility=")) + { + const(char)[] vis = arg["-visibility=".length .. $]; + + switch (vis) + { + case "default": + driverParams.exportVisibility = ExpVis.default_; + break; + case "hidden": + driverParams.exportVisibility = ExpVis.hidden; + break; + case "public": + driverParams.exportVisibility = ExpVis.public_; + break; + default: + error("unknown visibility '%.*s', must be 'default', 'hidden' or 'public'", cast(int) vis.length, vis.ptr); + } + } + else if (startsWith(p + 1, "dllimport=")) + { + const(char)[] imp = arg["-dllimport=".length .. $]; + + switch (imp) + { + case "none": + driverParams.symImport = SymImport.none; + break; + case "defaultLibsOnly": + driverParams.symImport = SymImport.defaultLibsOnly; + break; + case "all": + driverParams.symImport = SymImport.all; + break; + default: + error("unknown dllimport '%.*s', must be 'none', 'defaultLibsOnly' or 'all'", cast(int) imp.length, imp.ptr); + } + } else if (arg == "-fIBT") { driverParams.ibt = true; diff --git a/runtime/druntime/Makefile b/runtime/druntime/Makefile index 06f39779806..50e4104d2c6 100644 --- a/runtime/druntime/Makefile +++ b/runtime/druntime/Makefile @@ -110,6 +110,9 @@ else DFLAGS:=$(UDFLAGS) -inline # unittests don't compile with -inline endif +SHAREDFLAGS:=$(if $(findstring $(OS),windows),-visibility=public -mscrtlib=msvcrt,-fPIC) +SOLIBS:=$(if $(findstring $(OS),windows),msvcrt.lib legacy_stdio_definitions.lib,-L-lpthread -L-lm) + UTFLAGS:=-version=CoreUnittest -unittest -checkaction=context # Set PHOBOS_DFLAGS (for linking against Phobos) @@ -125,7 +128,8 @@ ROOT_OF_THEM_ALL = ../generated ROOT = $(ROOT_OF_THEM_ALL)/$(OS)/$(BUILD)/$(MODEL) OBJDIR=obj/$(OS)/$(BUILD)/$(MODEL) DRUNTIME=$(ROOT)/$(if $(findstring $(OS),windows),,lib)druntime$(DOTLIB) -DRUNTIMESO=$(ROOT)/$(if $(findstring $(OS),windows),,lib)druntime$(DOTDLL) +DRUNTIMESO_BASE=$(ROOT)/$(if $(findstring $(OS),windows),druntime_shared,libdruntime) +DRUNTIMESO=$(DRUNTIMESO_BASE)$(DOTDLL) DRUNTIMESOOBJ=$(DRUNTIMESO)$(DOTOBJ) DRUNTIMESOLIB=$(DRUNTIMESO)$(DOTLIB) @@ -401,11 +405,12 @@ $(ROOT)/valgrind$(DOTOBJ) : src/etc/valgrind/valgrind.c src/etc/valgrind/valgrin ######################## Create a shared library ############################## -$(DRUNTIMESO) $(DRUNTIMESOLIB) dll: DFLAGS+=-version=Shared $(if $(findstring $(OS),windows),,-fPIC) +$(DRUNTIMESO) $(DRUNTIMESOLIB) dll: DFLAGS+=-version=Shared $(SHAREDFLAGS) dll: $(DRUNTIMESOLIB) +dll_so: $(DRUNTIMESO) $(DRUNTIMESO): $(OBJS) $(SRCS) $(DMD) - $(DMD) -shared -debuglib= -defaultlib= -of$(DRUNTIMESO) $(DFLAGS) $(SRCS) $(OBJS) $(LINKDL) -L-lpthread -L-lm + $(DMD) -shared -debuglib= -defaultlib= -of$(DRUNTIMESO) $(DFLAGS) $(SRCS) $(OBJS) $(LINKDL) $(SOLIBS) $(DRUNTIMESOLIB): $(OBJS) $(SRCS) $(DMD) $(DMD) -c $(if $(findstring $(OS),windows),,-fPIC) -of$(DRUNTIMESOOBJ) $(DFLAGS) $(SRCS) @@ -471,13 +476,14 @@ $(ROOT)/unittest/test_runner$(DOTEXE): $(OBJS) $(SRCS) src/test_runner.d $(DMD) else UT_DRUNTIME:=$(ROOT)/unittest/libdruntime-ut$(DOTDLL) +UT_DRUNTIMELIB:=$(ROOT)/unittest/libdruntime-ut$(if $(findstring $(OS),windows),$(DOTLIB),$(DOTDLL)) -$(UT_DRUNTIME): UDFLAGS+=-version=Shared $(if $(findstring $(OS),windows),,-fPIC) +$(UT_DRUNTIME): UDFLAGS+=-version=Shared $(SHAREDFLAGS) $(UT_DRUNTIME): $(OBJS) $(SRCS) $(DMD) - $(DMD) $(UDFLAGS) -shared $(UTFLAGS) -of$@ $(SRCS) $(OBJS) $(LINKDL) -defaultlib= $(if $(findstring $(OS),windows),user32.lib,-L-lpthread -L-lm) + $(DMD) $(UDFLAGS) -shared $(UTFLAGS) -of$@ $(SRCS) $(OBJS) $(LINKDL) -defaultlib= $(if $(findstring $(OS),windows),user32.lib -L/IMPLIB:$(UT_DRUNTIMELIB),) $(SOLIBS) $(ROOT)/unittest/test_runner$(DOTEXE): $(UT_DRUNTIME) src/test_runner.d $(DMD) - $(DMD) $(UDFLAGS) -of$@ src/test_runner.d -L$(UT_DRUNTIME) -defaultlib= $(if $(findstring $(OS),windows),user32.lib,-L-lpthread -L-lm) + $(DMD) $(UDFLAGS) -of$@ src/test_runner.d -L$(UT_DRUNTIMELIB) -defaultlib= $(if $(findstring $(OS),windows),-dllimport=defaultLibsOnly user32.lib,-L-lpthread -L-lm) endif diff --git a/runtime/druntime/src/rt/msvc.d b/runtime/druntime/src/rt/msvc.d index aa7acc9e60b..e02fac8854d 100644 --- a/runtime/druntime/src/rt/msvc.d +++ b/runtime/druntime/src/rt/msvc.d @@ -201,6 +201,8 @@ int _msvc_fileno(_iobuf* stream) } +// MSVCRT.lib only provides _strdup +mixin declareAlternateName!("strdup", "_strdup"); /** * 32-bit x86 MS VC runtimes lack most single-precision math functions. diff --git a/runtime/druntime/src/rt/sections.d b/runtime/druntime/src/rt/sections.d index b086dc893e6..a84a5c6bcdf 100644 --- a/runtime/druntime/src/rt/sections.d +++ b/runtime/druntime/src/rt/sections.d @@ -80,7 +80,10 @@ static assert(is(typeof(&initTLSRanges) RT == return) && is(typeof(&finiTLSRanges) == void function(RT) nothrow @nogc) && is(typeof(&scanTLSRanges) == void function(RT, scope void delegate(void*, void*) nothrow) nothrow)); -version (Shared) +version (Windows) +{ +} +else version (Shared) { static assert(is(typeof(&pinLoadedLibraries) == void* function() nothrow @nogc)); static assert(is(typeof(&unpinLoadedLibraries) == void function(void*) nothrow @nogc)); diff --git a/runtime/druntime/test/common.mak b/runtime/druntime/test/common.mak index 132fc7e5891..f091fe99292 100644 --- a/runtime/druntime/test/common.mak +++ b/runtime/druntime/test/common.mak @@ -19,6 +19,7 @@ LDL:=$(subst -L,,$(LINKDL)) # -ldl SRC:=src GENERATED:=./generated ROOT:=$(GENERATED)/$(OS)/$(BUILD)/$(MODEL) +DRUNTIME_IMPLIB:=$(subst .dll,.lib,$(DRUNTIMESO)) MODEL_FLAG:=$(if $(findstring $(MODEL),default),,-m$(MODEL)) CFLAGS_BASE:=$(if $(findstring $(OS),windows),/Wall,$(MODEL_FLAG) $(PIC) -Wall) @@ -27,7 +28,7 @@ ifeq (osx64,$(OS)$(MODEL)) endif DFLAGS:=$(MODEL_FLAG) $(PIC) -w -I../../src -I../../import -I$(SRC) -defaultlib= -preview=dip1000 $(if $(findstring $(OS),windows),,-L-lpthread -L-lm $(LINKDL)) # LINK_SHARED may be set by importing makefile -DFLAGS+=$(if $(LINK_SHARED),-L$(DRUNTIMESO),-L$(DRUNTIME)) +DFLAGS+=$(if $(LINK_SHARED),-L$(DRUNTIME_IMPLIB) $(if $(findstring $(OS),windows),-dllimport=defaultLibsOnly),-L$(DRUNTIME)) ifeq ($(BUILD),debug) DFLAGS+=-g -debug CFLAGS:=$(CFLAGS_BASE) $(if $(findstring $(OS),windows),/Zi,-g) diff --git a/runtime/druntime/test/shared/Makefile b/runtime/druntime/test/shared/Makefile index 94cdbd6b2e7..6c404758c8d 100644 --- a/runtime/druntime/test/shared/Makefile +++ b/runtime/druntime/test/shared/Makefile @@ -1,5 +1,5 @@ # druntime DLL not supported on Windows yet -LINK_SHARED:=$(if $(findstring $(OS),windows),,1) +LINK_SHARED:=$(if $(findstring $(OS),windows),$(SHARED),1) include ../common.mak # affected by LINK_SHARED! @@ -8,6 +8,9 @@ include ../common.mak # affected by LINK_SHARED! ifeq (windows,$(OS)) TESTS:=loadlibwin dllrefcount dllgc dynamiccast +ifeq ($(SHARED),1) +DFLAGS+=-version=SharedRuntime +endif all: $(addprefix $(ROOT)/,$(addsuffix .done,$(TESTS))) diff --git a/runtime/druntime/test/shared/src/dynamiccast.d b/runtime/druntime/test/shared/src/dynamiccast.d index 2efcff21f67..9bd19de0645 100644 --- a/runtime/druntime/test/shared/src/dynamiccast.d +++ b/runtime/druntime/test/shared/src/dynamiccast.d @@ -72,7 +72,8 @@ else return null; } - version (DigitalMars) version (Win64) version = DMD_Win64; + version (DigitalMars) version (Win64) version = NoExceptions; + version (SharedRuntime) version (DigitalMars) version (Win32) version = NoExceptions; void main(string[] args) { @@ -101,7 +102,7 @@ else auto o = getFunc!(Object function(Object))("foo")(c); assert(cast(C) o); - version (DMD_Win64) + version (NoExceptions) { // FIXME: apparent crash & needs more work, see https://github.com/dlang/druntime/pull/2874 fclose(fopen("dynamiccast_endbar", "w")); From e3f4f3541d904ac232d459b578ddd7b6c0de5b07 Mon Sep 17 00:00:00 2001 From: Walter Bright Date: Sat, 30 Dec 2023 13:04:17 -0800 Subject: [PATCH 170/215] getLines() shouldn't be reading files --- dmd/errors.d | 4 +-- dmd/file_manager.d | 71 +++++++++++++++++++++------------------------- 2 files changed, 35 insertions(+), 40 deletions(-) diff --git a/dmd/errors.d b/dmd/errors.d index 4208c60758b..673c6e4b000 100644 --- a/dmd/errors.d +++ b/dmd/errors.d @@ -661,9 +661,9 @@ private void verrorPrint(const(char)* format, va_list ap, ref ErrorInfo info) { import dmd.root.filename : FileName; const fileName = FileName(loc.filename.toDString); - if (auto file = global.fileManager.lookup(fileName)) + if (auto text = global.fileManager.lookup(fileName)) { - const(char)[][] lines = global.fileManager.getLines(fileName); + const(char[])[] lines = global.fileManager.splitTextIntoLines(cast(const(char[])) text); if (loc.linnum - 1 < lines.length) { auto line = lines[loc.linnum - 1]; diff --git a/dmd/file_manager.d b/dmd/file_manager.d index a0e5d0519c8..3694dec5dae 100644 --- a/dmd/file_manager.d +++ b/dmd/file_manager.d @@ -282,59 +282,54 @@ nothrow: } /** - * Looks up the given filename from the internal file buffer table, and returns the lines within the file. - * If the file does not already exist within the table, it will be read from the filesystem. - * If it has been read before, - * - * Returns: the loaded source file if it was found in memory, - * otherwise `null` + * Take `text` and slice it up into lines. + * Params: + * text = character text + * Returns: + * GC allocated array of slices into `text`, one slice per line */ - const(char)[][] getLines(FileName file) + const(char)[][] splitTextIntoLines(const char[] text) { const(char)[][] lines; - if (const buffer = lookup(file)) + size_t start, end; + for (auto i = 0; i < text.length; i++) { - const slice = buffer; - size_t start, end; - for (auto i = 0; i < slice.length; i++) + const c = text[i]; + if (c == '\n' || c == '\r') { - const c = slice[i]; - if (c == '\n' || c == '\r') + if (i != 0) { - if (i != 0) - { - end = i; - // Appending lines one at a time will certainly be slow - lines ~= cast(const(char)[])slice[start .. end]; - } - // Check for Windows-style CRLF newlines - if (c == '\r') + end = i; + // Appending lines one at a time will certainly be slow + lines ~= cast(const(char)[])text[start .. end]; + } + // Check for Windows-style CRLF newlines + if (c == '\r') + { + if (text.length > i + 1 && text[i + 1] == '\n') { - if (slice.length > i + 1 && slice[i + 1] == '\n') - { - // This is a CRLF sequence, skip over two characters - start = i + 2; - i++; - } - else - { - // Just a CR sequence - start = i + 1; - } + // This is a CRLF sequence, skip over two characters + start = i + 2; + i++; } else { - // The next line should start after the LF sequence + // Just a CR sequence start = i + 1; } } + else + { + // The next line should start after the LF sequence + start = i + 1; + } } + } - if (slice[$ - 1] != '\r' && slice[$ - 1] != '\n') - { - end = slice.length; - lines ~= cast(const(char)[])slice[start .. end]; - } + if (text[$ - 1] != '\r' && text[$ - 1] != '\n') + { + end = text.length; + lines ~= cast(const(char)[])text[start .. end]; } return lines; From 0055e6a86365f3fa865561b2c5763b1d209b0707 Mon Sep 17 00:00:00 2001 From: Jeremy Date: Sun, 31 Dec 2023 17:09:16 +1300 Subject: [PATCH 171/215] supply definitions for if_nameindex_t and related symbols on musl libc (dlang/dmd!15971) --- runtime/druntime/src/core/sys/posix/net/if_.d | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/runtime/druntime/src/core/sys/posix/net/if_.d b/runtime/druntime/src/core/sys/posix/net/if_.d index 3713673e4bc..7fadcd884c4 100644 --- a/runtime/druntime/src/core/sys/posix/net/if_.d +++ b/runtime/druntime/src/core/sys/posix/net/if_.d @@ -143,6 +143,21 @@ else version (CRuntime_Bionic) uint if_nametoindex(const scope char*); char* if_indextoname(uint, char*); } +else version (CRuntime_Musl) +{ + struct if_nameindex_t + { + uint if_index; + char* if_name; + } + + enum IF_NAMESIZE = 16; + + uint if_nametoindex(const scope char*); + char* if_indextoname(uint, char*); + if_nameindex_t* if_nameindex(); + void if_freenameindex(if_nameindex_t*); +} else version (CRuntime_UClibc) { struct if_nameindex_t From 0da19c9c9e405495254ed30038103f96dbecb596 Mon Sep 17 00:00:00 2001 From: Walter Bright Date: Sat, 30 Dec 2023 21:50:11 -0800 Subject: [PATCH 172/215] change splitTextIntoLines() to splitLines() (dlang/dmd!15972) --- dmd/errors.d | 16 +++--- dmd/file_manager.d | 124 +++++++++++++++++++++++++++++++-------------- 2 files changed, 95 insertions(+), 45 deletions(-) diff --git a/dmd/errors.d b/dmd/errors.d index 673c6e4b000..277818d9819 100644 --- a/dmd/errors.d +++ b/dmd/errors.d @@ -663,28 +663,32 @@ private void verrorPrint(const(char)* format, va_list ap, ref ErrorInfo info) const fileName = FileName(loc.filename.toDString); if (auto text = global.fileManager.lookup(fileName)) { - const(char[])[] lines = global.fileManager.splitTextIntoLines(cast(const(char[])) text); - if (loc.linnum - 1 < lines.length) + auto range = global.fileManager.splitLines(cast(const(char[])) text); + size_t linnum; + foreach (line; range) { - auto line = lines[loc.linnum - 1]; + ++linnum; + if (linnum != loc.linnum) + continue; if (loc.charnum < line.length) { fprintf(stderr, "%.*s\n", cast(int)line.length, line.ptr); // The number of column bytes and the number of display columns // occupied by a character are not the same for non-ASCII charaters. // https://issues.dlang.org/show_bug.cgi?id=21849 - size_t c = 0; - while (c < loc.charnum - 1) + size_t col = 0; + while (col < loc.charnum - 1) { import dmd.root.utf : utf_decodeChar; dchar u; - const msg = utf_decodeChar(line, c, u); + const msg = utf_decodeChar(line, col, u); assert(msg is null, msg); fputc(' ', stderr); } fputc('^', stderr); fputc('\n', stderr); } + break; } } } diff --git a/dmd/file_manager.d b/dmd/file_manager.d index 3694dec5dae..0ea78b5f954 100644 --- a/dmd/file_manager.d +++ b/dmd/file_manager.d @@ -10,6 +10,7 @@ module dmd.file_manager; +import core.stdc.stdio; import dmd.root.stringtable : StringTable; import dmd.root.file : File, Buffer; import dmd.root.filename : FileName, isDirSeparator; @@ -281,58 +282,103 @@ nothrow: return fb; } - /** - * Take `text` and slice it up into lines. + /********************************** + * Take `text` and turn it into an InputRange that emits + * slices into `text` for each line. * Params: - * text = character text + * text = array of characters * Returns: - * GC allocated array of slices into `text`, one slice per line + * InputRange accessing `text` as a sequence of lines + * Reference: + * `std.string.splitLines()` */ - const(char)[][] splitTextIntoLines(const char[] text) + auto splitLines(const char[] text) { - const(char)[][] lines; - size_t start, end; - for (auto i = 0; i < text.length; i++) + struct Range { - const c = text[i]; - if (c == '\n' || c == '\r') + @safe: + @nogc: + nothrow: + pure: + private: + + const char[] text; + size_t index; // index of start of line + size_t eolIndex; // index of end of line before newline characters + size_t nextIndex; // index past end of line + + public this(const char[] text) { - if (i != 0) - { - end = i; - // Appending lines one at a time will certainly be slow - lines ~= cast(const(char)[])text[start .. end]; - } - // Check for Windows-style CRLF newlines - if (c == '\r') + this.text = text; + } + + public bool empty() { return index == text.length; } + + public void popFront() { advance(); index = nextIndex; } + + public const(char)[] front() { advance(); return text[index .. eolIndex]; } + + private void advance() + { + if (index != nextIndex) // if already advanced + return; + + for (size_t i = index; i < text.length; ++i) { - if (text.length > i + 1 && text[i + 1] == '\n') - { - // This is a CRLF sequence, skip over two characters - start = i + 2; - i++; - } - else + switch (text[i]) { - // Just a CR sequence - start = i + 1; + case '\v', '\f', '\n': + eolIndex = i; + nextIndex = i + 1; + return; + + case '\r': + if (i + 1 < text.length && text[i + 1] == '\n') // decode "\r\n" + { + eolIndex = i; + nextIndex = i + 2; + return; + } + eolIndex = i; + nextIndex = i + 1; + return; + + /* Manually decode: + * NEL is C2 85 + */ + case 0xC2: + if (i + 1 < text.length && text[i + 1] == 0x85) + { + eolIndex = i; + nextIndex = i + 2; + return; + } + break; + + /* Manually decode: + * lineSep is E2 80 A8 + * paraSep is E2 80 A9 + */ + case 0xE2: + if (i + 2 < text.length && + text[i + 1] == 0x80 && + (text[i + 2] == 0xA8 || text[i + 2] == 0xA9) + ) + { + eolIndex = i; + nextIndex = i + 3; + return; + } + break; + + default: + break; } } - else - { - // The next line should start after the LF sequence - start = i + 1; - } } } - if (text[$ - 1] != '\r' && text[$ - 1] != '\n') - { - end = text.length; - lines ~= cast(const(char)[])text[start .. end]; - } - - return lines; + return Range(text); } /** From 5326f946d6becf2995353400d5e4954d1939816a Mon Sep 17 00:00:00 2001 From: Danil Sidoruk Date: Mon, 1 Jan 2024 12:23:03 +0300 Subject: [PATCH 173/215] Fix issue 20369 - shadowed variable in foreach loop always considered "foreach variable" (dlang/dmd!15934) * Fix issue 20369 - shadowed variable in foreach loop always considered "foreach variable" * Remove unintuitive phrase in deprecation message * Fix deprecation message in test * Add original variable's line information in deprecation (error) message --- dmd/expressionsem.d | 5 ++++- tests/dmd/fail_compilation/diag11425.d | 3 ++- tests/dmd/fail_compilation/fail110.d | 9 ++++++--- tests/dmd/fail_compilation/fail2195.d | 3 ++- tests/dmd/fail_compilation/fail93.d | 3 ++- 5 files changed, 16 insertions(+), 7 deletions(-) diff --git a/dmd/expressionsem.d b/dmd/expressionsem.d index 8a01644d141..f9bf70cfa1a 100644 --- a/dmd/expressionsem.d +++ b/dmd/expressionsem.d @@ -6813,11 +6813,14 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor { if (sc.func.fes) { - deprecation(e.loc, "%s `%s` is shadowing %s `%s`. Rename the `foreach` variable.", s.kind(), s.ident.toChars(), s2.kind(), s2.toPrettyChars()); + deprecation(e.loc, "%s `%s` is shadowing %s `%s`", s.kind(), s.ident.toChars(), s2.kind(), s2.toPrettyChars()); + deprecationSupplemental(s2.loc, "declared here"); + } else { error(e.loc, "%s `%s` is shadowing %s `%s`", s.kind(), s.ident.toChars(), s2.kind(), s2.toPrettyChars()); + errorSupplemental(s2.loc, "declared here"); return setError(); } } diff --git a/tests/dmd/fail_compilation/diag11425.d b/tests/dmd/fail_compilation/diag11425.d index f8edc5c7867..dfcddaa5f67 100644 --- a/tests/dmd/fail_compilation/diag11425.d +++ b/tests/dmd/fail_compilation/diag11425.d @@ -1,7 +1,8 @@ /* TEST_OUTPUT: --- -fail_compilation/diag11425.d(13): Error: variable `x` is shadowing variable `diag11425.main.x` +fail_compilation/diag11425.d(14): Error: variable `x` is shadowing variable `diag11425.main.x` +fail_compilation/diag11425.d(11): declared here --- */ diff --git a/tests/dmd/fail_compilation/fail110.d b/tests/dmd/fail_compilation/fail110.d index a13922b0fde..4ba2a8c487e 100644 --- a/tests/dmd/fail_compilation/fail110.d +++ b/tests/dmd/fail_compilation/fail110.d @@ -1,9 +1,12 @@ /* TEST_OUTPUT: --- -fail_compilation/fail110.d(16): Error: variable `i` is shadowing variable `fail110.main.i` -fail_compilation/fail110.d(17): Error: variable `i` is shadowing variable `fail110.main.i` -fail_compilation/fail110.d(18): Error: variable `i` is shadowing variable `fail110.main.i` +fail_compilation/fail110.d(19): Error: variable `i` is shadowing variable `fail110.main.i` +fail_compilation/fail110.d(17): declared here +fail_compilation/fail110.d(20): Error: variable `i` is shadowing variable `fail110.main.i` +fail_compilation/fail110.d(17): declared here +fail_compilation/fail110.d(21): Error: variable `i` is shadowing variable `fail110.main.i` +fail_compilation/fail110.d(17): declared here --- */ diff --git a/tests/dmd/fail_compilation/fail2195.d b/tests/dmd/fail_compilation/fail2195.d index 0eff0663d4b..6f6cd53b0e3 100644 --- a/tests/dmd/fail_compilation/fail2195.d +++ b/tests/dmd/fail_compilation/fail2195.d @@ -3,7 +3,8 @@ /* TEST_OUTPUT: --- -fail_compilation/fail2195.d(16): Deprecation: variable `variable` is shadowing variable `fail2195.main.variable`. Rename the `foreach` variable. +fail_compilation/fail2195.d(17): Deprecation: variable `variable` is shadowing variable `fail2195.main.variable` +fail_compilation/fail2195.d(14): declared here --- */ diff --git a/tests/dmd/fail_compilation/fail93.d b/tests/dmd/fail_compilation/fail93.d index b9ad2941be7..29893959b17 100644 --- a/tests/dmd/fail_compilation/fail93.d +++ b/tests/dmd/fail_compilation/fail93.d @@ -1,7 +1,8 @@ /* TEST_OUTPUT: --- -fail_compilation/fail93.d(13): Error: variable `i` is shadowing variable `fail93.main.i` +fail_compilation/fail93.d(14): Error: variable `i` is shadowing variable `fail93.main.i` +fail_compilation/fail93.d(13): declared here --- */ From a5594e48075b22e0cfab9a343b5d816deede9d7a Mon Sep 17 00:00:00 2001 From: Iain Buclaw Date: Sun, 31 Dec 2023 00:18:55 +0100 Subject: [PATCH 174/215] Update GNU implementation of internal atomic.d The DigitalMars implementation doesn't reject anywhere near enough of the invalid MemoryOrder cases for atomicLoad, store, exchange, and cas. So until these cases also become static asserts, just silently rewrite them into valid MemoryOrders for the benefit of core.stdc.stdatomic. --- runtime/druntime/src/core/internal/atomic.d | 91 ++++++++++++++++----- 1 file changed, 71 insertions(+), 20 deletions(-) diff --git a/runtime/druntime/src/core/internal/atomic.d b/runtime/druntime/src/core/internal/atomic.d index 25b2c70f65a..3fd5d4a595d 100644 --- a/runtime/druntime/src/core/internal/atomic.d +++ b/runtime/druntime/src/core/internal/atomic.d @@ -688,39 +688,57 @@ else version (GNU) import gcc.builtins; import gcc.config; + // Targets where MemoryOrder.acq_rel is sufficiently cheaper than using + // MemoryOrder.seq, used when the MemoryOrder requested is not valid for + // a given atomic operation. + version (IA64) + private enum PreferAcquireRelease = true; + else version (PPC) + private enum PreferAcquireRelease = true; + else version (PPC64) + private enum PreferAcquireRelease = true; + else + private enum PreferAcquireRelease = false; + enum IsAtomicLockFree(T) = __atomic_is_lock_free(T.sizeof, null); inout(T) atomicLoad(MemoryOrder order = MemoryOrder.seq, T)(inout(T)* src) pure nothrow @nogc @trusted if (CanCAS!T) { + // MemoryOrder.rel and MemoryOrder.acq_rel are not valid for load. static assert(order != MemoryOrder.rel, "invalid MemoryOrder for atomicLoad()"); + static if (order == MemoryOrder.acq_rel) + enum smodel = PreferAcquireRelease ? MemoryOrder.acq : MemoryOrder.seq; + else + enum smodel = order; + static if (GNU_Have_Atomics || GNU_Have_LibAtomic) { static if (T.sizeof == ubyte.sizeof) { - ubyte value = __atomic_load_1(cast(shared)src, order); + ubyte value = __atomic_load_1(cast(shared)src, smodel); return *cast(typeof(return)*)&value; } else static if (T.sizeof == ushort.sizeof) { - ushort value = __atomic_load_2(cast(shared)src, order); + ushort value = __atomic_load_2(cast(shared)src, smodel); return *cast(typeof(return)*)&value; } else static if (T.sizeof == uint.sizeof) { - uint value = __atomic_load_4(cast(shared)src, order); + uint value = __atomic_load_4(cast(shared)src, smodel); return *cast(typeof(return)*)&value; } else static if (T.sizeof == ulong.sizeof && GNU_Have_64Bit_Atomics) { - ulong value = __atomic_load_8(cast(shared)src, order); + ulong value = __atomic_load_8(cast(shared)src, smodel); return *cast(typeof(return)*)&value; } else static if (GNU_Have_LibAtomic) { T value; - __atomic_load(T.sizeof, cast(shared)src, &value, order); + __atomic_load(T.sizeof, cast(shared)src, &value, smodel); return *cast(typeof(return)*)&value; } else @@ -737,20 +755,26 @@ else version (GNU) void atomicStore(MemoryOrder order = MemoryOrder.seq, T)(T* dest, T value) pure nothrow @nogc @trusted if (CanCAS!T) { + // MemoryOrder.acq and MemoryOrder.acq_rel are not valid for store. static assert(order != MemoryOrder.acq, "Invalid MemoryOrder for atomicStore()"); + static if (order == MemoryOrder.acq_rel) + enum smodel = PreferAcquireRelease ? MemoryOrder.rel : MemoryOrder.seq; + else + enum smodel = order; + static if (GNU_Have_Atomics || GNU_Have_LibAtomic) { static if (T.sizeof == ubyte.sizeof) - __atomic_store_1(cast(shared)dest, *cast(ubyte*)&value, order); + __atomic_store_1(cast(shared)dest, *cast(ubyte*)&value, smodel); else static if (T.sizeof == ushort.sizeof) - __atomic_store_2(cast(shared)dest, *cast(ushort*)&value, order); + __atomic_store_2(cast(shared)dest, *cast(ushort*)&value, smodel); else static if (T.sizeof == uint.sizeof) - __atomic_store_4(cast(shared)dest, *cast(uint*)&value, order); + __atomic_store_4(cast(shared)dest, *cast(uint*)&value, smodel); else static if (T.sizeof == ulong.sizeof && GNU_Have_64Bit_Atomics) - __atomic_store_8(cast(shared)dest, *cast(ulong*)&value, order); + __atomic_store_8(cast(shared)dest, *cast(ulong*)&value, smodel); else static if (GNU_Have_LibAtomic) - __atomic_store(T.sizeof, cast(shared)dest, cast(void*)&value, order); + __atomic_store(T.sizeof, cast(shared)dest, cast(void*)&value, smodel); else static assert(0, "Invalid template type specified."); } @@ -823,30 +847,36 @@ else version (GNU) { static if (GNU_Have_Atomics || GNU_Have_LibAtomic) { + // MemoryOrder.acq is not valid for exchange. + static if (order == MemoryOrder.acq) + enum smodel = PreferAcquireRelease ? MemoryOrder.acq_rel : MemoryOrder.seq; + else + enum smodel = order; + static if (T.sizeof == byte.sizeof) { - ubyte res = __atomic_exchange_1(cast(shared)dest, *cast(ubyte*)&value, order); + ubyte res = __atomic_exchange_1(cast(shared)dest, *cast(ubyte*)&value, smodel); return *cast(typeof(return)*)&res; } else static if (T.sizeof == short.sizeof) { - ushort res = __atomic_exchange_2(cast(shared)dest, *cast(ushort*)&value, order); + ushort res = __atomic_exchange_2(cast(shared)dest, *cast(ushort*)&value, smodel); return *cast(typeof(return)*)&res; } else static if (T.sizeof == int.sizeof) { - uint res = __atomic_exchange_4(cast(shared)dest, *cast(uint*)&value, order); + uint res = __atomic_exchange_4(cast(shared)dest, *cast(uint*)&value, smodel); return *cast(typeof(return)*)&res; } else static if (T.sizeof == long.sizeof && GNU_Have_64Bit_Atomics) { - ulong res = __atomic_exchange_8(cast(shared)dest, *cast(ulong*)&value, order); + ulong res = __atomic_exchange_8(cast(shared)dest, *cast(ulong*)&value, smodel); return *cast(typeof(return)*)&res; } else static if (GNU_Have_LibAtomic) { T res = void; - __atomic_exchange(T.sizeof, cast(shared)dest, cast(void*)&value, &res, order); + __atomic_exchange(T.sizeof, cast(shared)dest, cast(void*)&value, &res, smodel); return res; } else @@ -894,21 +924,42 @@ else version (GNU) static if (GNU_Have_Atomics || GNU_Have_LibAtomic) { + static if (fail == MemoryOrder.rel || fail == MemoryOrder.acq_rel) + { + // MemoryOrder.rel and MemoryOrder.acq_rel are not valid failure models. + enum smodel = (succ != MemoryOrder.seq && PreferAcquireRelease) + ? MemoryOrder.acq_rel : MemoryOrder.seq; + enum fmodel = (succ != MemoryOrder.seq && PreferAcquireRelease) + ? MemoryOrder.raw : MemoryOrder.seq; + } + else static if (fail > succ) + { + // Failure memory model cannot be stronger than success. + enum smodel = (fail != MemoryOrder.seq && PreferAcquireRelease) + ? MemoryOrder.acq_rel : MemoryOrder.seq; + enum fmodel = fail; + } + else + { + enum smodel = succ; + enum fmodel = fail; + } + static if (T.sizeof == byte.sizeof) res = __atomic_compare_exchange_1(cast(shared)dest, compare, *cast(ubyte*)&value, - weak, succ, fail); + weak, smodel, fmodel); else static if (T.sizeof == short.sizeof) res = __atomic_compare_exchange_2(cast(shared)dest, compare, *cast(ushort*)&value, - weak, succ, fail); + weak, smodel, fmodel); else static if (T.sizeof == int.sizeof) res = __atomic_compare_exchange_4(cast(shared)dest, compare, *cast(uint*)&value, - weak, succ, fail); + weak, smodel, fmodel); else static if (T.sizeof == long.sizeof && GNU_Have_64Bit_Atomics) res = __atomic_compare_exchange_8(cast(shared)dest, compare, *cast(ulong*)&value, - weak, succ, fail); + weak, smodel, fmodel); else static if (GNU_Have_LibAtomic) res = __atomic_compare_exchange(T.sizeof, cast(shared)dest, compare, cast(void*)&value, - succ, fail); + smodel, fmodel); else static assert(0, "Invalid template type specified."); } From 2a66b5e11ab3eaa8f1ce7fda6f823956288823fa Mon Sep 17 00:00:00 2001 From: Iain Buclaw Date: Mon, 1 Jan 2024 18:40:37 +0100 Subject: [PATCH 175/215] Update copyright years of dmd sources to 2024 --- dmd/access.d | 2 +- dmd/aggregate.d | 2 +- dmd/aggregate.h | 2 +- dmd/aliasthis.d | 2 +- dmd/aliasthis.h | 2 +- dmd/argtypes_aarch64.d | 2 +- dmd/argtypes_sysv_x64.d | 2 +- dmd/argtypes_x86.d | 2 +- dmd/arrayop.d | 2 +- dmd/arraytypes.d | 2 +- dmd/arraytypes.h | 2 +- dmd/ast_node.d | 2 +- dmd/ast_node.h | 2 +- dmd/astenums.d | 2 +- dmd/asttypename.d | 2 +- dmd/attrib.d | 2 +- dmd/attrib.h | 2 +- dmd/blockexit.d | 2 +- dmd/builtin.d | 2 +- dmd/canthrow.d | 2 +- dmd/chkformat.d | 2 +- dmd/cli.d | 2 +- dmd/clone.d | 2 +- dmd/common/bitfields.d | 2 +- dmd/common/file.d | 2 +- dmd/common/int128.d | 2 +- dmd/common/outbuffer.d | 2 +- dmd/common/outbuffer.h | 2 +- dmd/common/smallbuffer.d | 2 +- dmd/compiler.d | 2 +- dmd/compiler.h | 2 +- dmd/cond.d | 2 +- dmd/cond.h | 2 +- dmd/console.d | 2 +- dmd/constfold.d | 2 +- dmd/cparse.d | 2 +- dmd/cppmangle.d | 2 +- dmd/cppmanglewin.d | 2 +- dmd/ctfe.h | 2 +- dmd/ctfeexpr.d | 2 +- dmd/ctorflow.d | 2 +- dmd/dcast.d | 2 +- dmd/dclass.d | 2 +- dmd/declaration.d | 2 +- dmd/declaration.h | 2 +- dmd/delegatize.d | 2 +- dmd/denum.d | 2 +- dmd/dimport.d | 2 +- dmd/dinterpret.d | 2 +- dmd/dmacro.d | 2 +- dmd/dmangle.d | 2 +- dmd/dmodule.d | 2 +- dmd/doc.d | 2 +- dmd/doc.h | 2 +- dmd/dscope.d | 2 +- dmd/dstruct.d | 2 +- dmd/dsymbol.d | 2 +- dmd/dsymbol.h | 2 +- dmd/dsymbolsem.d | 2 +- dmd/dtemplate.d | 2 +- dmd/dtoh.d | 2 +- dmd/dversion.d | 2 +- dmd/entity.d | 2 +- dmd/enum.h | 2 +- dmd/errors.d | 2 +- dmd/errors.h | 2 +- dmd/errorsink.d | 2 +- dmd/escape.d | 2 +- dmd/expression.d | 2 +- dmd/expression.h | 2 +- dmd/expressionsem.d | 2 +- dmd/file_manager.d | 2 +- dmd/foreachvar.d | 2 +- dmd/frontend.h | 4 ++-- dmd/func.d | 2 +- dmd/globals.d | 4 ++-- dmd/globals.h | 2 +- dmd/gluelayer.d | 2 +- dmd/hdrgen.d | 2 +- dmd/hdrgen.h | 2 +- dmd/iasmgcc.d | 2 +- dmd/id.d | 2 +- dmd/id.h | 2 +- dmd/identifier.d | 2 +- dmd/identifier.h | 2 +- dmd/impcnvtab.d | 2 +- dmd/imphint.d | 2 +- dmd/import.h | 2 +- dmd/importc.d | 2 +- dmd/init.d | 2 +- dmd/init.h | 2 +- dmd/initsem.d | 2 +- dmd/inline.d | 2 +- dmd/inlinecost.d | 2 +- dmd/intrange.d | 2 +- dmd/json.d | 2 +- dmd/json.h | 2 +- dmd/lambdacomp.d | 2 +- dmd/lexer.d | 2 +- dmd/location.d | 2 +- dmd/main.d | 2 +- dmd/mangle.h | 2 +- dmd/mars.d | 2 +- dmd/module.h | 2 +- dmd/mtype.d | 2 +- dmd/mtype.h | 2 +- dmd/mustuse.d | 2 +- dmd/nogc.d | 2 +- dmd/nspace.d | 2 +- dmd/nspace.h | 2 +- dmd/ob.d | 2 +- dmd/objc.d | 2 +- dmd/objc.h | 2 +- dmd/opover.d | 2 +- dmd/optimize.d | 2 +- dmd/parse.d | 2 +- dmd/postordervisitor.d | 2 +- dmd/printast.d | 2 +- dmd/root/aav.d | 2 +- dmd/root/array.d | 2 +- dmd/root/array.h | 2 +- dmd/root/bitarray.d | 2 +- dmd/root/bitarray.h | 2 +- dmd/root/complex.d | 2 +- dmd/root/complex_t.h | 2 +- dmd/root/ctfloat.d | 2 +- dmd/root/ctfloat.h | 2 +- dmd/root/dcompat.h | 2 +- dmd/root/dsystem.h | 2 +- dmd/root/file.d | 2 +- dmd/root/filename.d | 2 +- dmd/root/filename.h | 2 +- dmd/root/hash.d | 2 +- dmd/root/longdouble.d | 2 +- dmd/root/longdouble.h | 2 +- dmd/root/man.d | 2 +- dmd/root/object.h | 2 +- dmd/root/optional.d | 2 +- dmd/root/optional.h | 2 +- dmd/root/port.d | 2 +- dmd/root/port.h | 2 +- dmd/root/region.d | 2 +- dmd/root/rmem.d | 2 +- dmd/root/rmem.h | 2 +- dmd/root/speller.d | 2 +- dmd/root/string.d | 2 +- dmd/root/stringtable.d | 2 +- dmd/root/utf.d | 2 +- dmd/rootobject.d | 2 +- dmd/safe.d | 2 +- dmd/sapply.d | 2 +- dmd/scope.h | 2 +- dmd/semantic2.d | 2 +- dmd/semantic3.d | 2 +- dmd/sideeffect.d | 2 +- dmd/statement.d | 2 +- dmd/statement.h | 2 +- dmd/statement_rewrite_walker.d | 2 +- dmd/statementsem.d | 2 +- dmd/staticassert.d | 2 +- dmd/staticassert.h | 2 +- dmd/staticcond.d | 2 +- dmd/stmtstate.d | 2 +- dmd/target.d | 2 +- dmd/target.h | 2 +- dmd/template.h | 2 +- dmd/templateparamsem.d | 2 +- dmd/tokens.d | 2 +- dmd/tokens.h | 2 +- dmd/traits.d | 2 +- dmd/typesem.d | 2 +- dmd/typinf.d | 2 +- dmd/typinf.h | 2 +- dmd/utils.d | 2 +- dmd/version.h | 2 +- dmd/visitor.d | 2 +- dmd/visitor.h | 2 +- dmd/vsoptions.d | 2 +- dmd/vsoptions.h | 2 +- 179 files changed, 181 insertions(+), 181 deletions(-) diff --git a/dmd/access.d b/dmd/access.d index 1010c140b68..8d022030173 100644 --- a/dmd/access.d +++ b/dmd/access.d @@ -3,7 +3,7 @@ * * Specification: $(LINK2 https://dlang.org/spec/attribute.html#visibility_attributes, Visibility Attributes) * - * Copyright: Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved + * Copyright: Copyright (C) 1999-2024 by The D Language Foundation, All Rights Reserved * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright) * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/access.d, _access.d) diff --git a/dmd/aggregate.d b/dmd/aggregate.d index d2d44d2a152..2d320426c23 100644 --- a/dmd/aggregate.d +++ b/dmd/aggregate.d @@ -4,7 +4,7 @@ * Specification: $(LINK2 https://dlang.org/spec/struct.html, Structs, Unions), * $(LINK2 https://dlang.org/spec/class.html, Class). * - * Copyright: Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved + * Copyright: Copyright (C) 1999-2024 by The D Language Foundation, All Rights Reserved * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright) * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/aggregate.d, _aggregate.d) diff --git a/dmd/aggregate.h b/dmd/aggregate.h index 98fa6bd1bb0..9abdd094b3f 100644 --- a/dmd/aggregate.h +++ b/dmd/aggregate.h @@ -1,6 +1,6 @@ /* Compiler implementation of the D programming language - * Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved + * Copyright (C) 1999-2024 by The D Language Foundation, All Rights Reserved * written by Walter Bright * https://www.digitalmars.com * Distributed under the Boost Software License, Version 1.0. diff --git a/dmd/aliasthis.d b/dmd/aliasthis.d index 0c156360fdc..0e063caa2fc 100644 --- a/dmd/aliasthis.d +++ b/dmd/aliasthis.d @@ -3,7 +3,7 @@ * * Specification: $(LINK2 https://dlang.org/spec/class.html#alias-this, Alias This) * - * Copyright: Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved + * Copyright: Copyright (C) 1999-2024 by The D Language Foundation, All Rights Reserved * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright) * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/aliasthis.d, _aliasthis.d) diff --git a/dmd/aliasthis.h b/dmd/aliasthis.h index 092490fd5de..88ba35319b3 100644 --- a/dmd/aliasthis.h +++ b/dmd/aliasthis.h @@ -1,6 +1,6 @@ /* Compiler implementation of the D programming language - * Copyright (C) 2009-2023 by The D Language Foundation, All Rights Reserved + * Copyright (C) 2009-2024 by The D Language Foundation, All Rights Reserved * written by Walter Bright * https://www.digitalmars.com * Distributed under the Boost Software License, Version 1.0. diff --git a/dmd/argtypes_aarch64.d b/dmd/argtypes_aarch64.d index 6fbf3ee8bef..6de36557038 100644 --- a/dmd/argtypes_aarch64.d +++ b/dmd/argtypes_aarch64.d @@ -1,7 +1,7 @@ /** * Break down a D type into basic (register) types for the AArch64 ABI. * - * Copyright: Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved + * Copyright: Copyright (C) 1999-2024 by The D Language Foundation, All Rights Reserved * Authors: Martin Kinkelin * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/argtypes_aarch64.d, _argtypes_aarch64.d) diff --git a/dmd/argtypes_sysv_x64.d b/dmd/argtypes_sysv_x64.d index 1ef32fcdf91..bf00e615da7 100644 --- a/dmd/argtypes_sysv_x64.d +++ b/dmd/argtypes_sysv_x64.d @@ -1,7 +1,7 @@ /** * Break down a D type into basic (register) types for the x86_64 System V ABI. * - * Copyright: Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved + * Copyright: Copyright (C) 1999-2024 by The D Language Foundation, All Rights Reserved * Authors: Martin Kinkelin * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/argtypes_sysv_x64.d, _argtypes_sysv_x64.d) diff --git a/dmd/argtypes_x86.d b/dmd/argtypes_x86.d index 6dc2c8deeff..ac4b29ae46a 100644 --- a/dmd/argtypes_x86.d +++ b/dmd/argtypes_x86.d @@ -1,7 +1,7 @@ /** * Break down a D type into basic (register) types for the 32-bit x86 ABI. * - * Copyright: Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved + * Copyright: Copyright (C) 1999-2024 by The D Language Foundation, All Rights Reserved * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright) * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/argtypes_x86.d, _argtypes_x86.d) diff --git a/dmd/arrayop.d b/dmd/arrayop.d index c3b8526a9a4..afe6054f4aa 100644 --- a/dmd/arrayop.d +++ b/dmd/arrayop.d @@ -3,7 +3,7 @@ * * Specification: $(LINK2 https://dlang.org/spec/arrays.html#array-operations, Array Operations) * - * Copyright: Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved + * Copyright: Copyright (C) 1999-2024 by The D Language Foundation, All Rights Reserved * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright) * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/arrayop.d, _arrayop.d) diff --git a/dmd/arraytypes.d b/dmd/arraytypes.d index 6634a6af1fc..feab9a49c7c 100644 --- a/dmd/arraytypes.d +++ b/dmd/arraytypes.d @@ -1,7 +1,7 @@ /** * Provide aliases for arrays of certain declarations or statements. * - * Copyright: Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved + * Copyright: Copyright (C) 1999-2024 by The D Language Foundation, All Rights Reserved * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright) * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/arraytypes.d, _arraytypes.d) diff --git a/dmd/arraytypes.h b/dmd/arraytypes.h index 05126a53d7e..779642813f5 100644 --- a/dmd/arraytypes.h +++ b/dmd/arraytypes.h @@ -1,6 +1,6 @@ /* Compiler implementation of the D programming language - * Copyright (C) 2006-2023 by The D Language Foundation, All Rights Reserved + * Copyright (C) 2006-2024 by The D Language Foundation, All Rights Reserved * written by Walter Bright * https://www.digitalmars.com * Distributed under the Boost Software License, Version 1.0. diff --git a/dmd/ast_node.d b/dmd/ast_node.d index 313c2bd3691..c8c95fa0782 100644 --- a/dmd/ast_node.d +++ b/dmd/ast_node.d @@ -1,7 +1,7 @@ /** * Defines the base class for all nodes which are part of the AST. * - * Copyright: Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved + * Copyright: Copyright (C) 1999-2024 by The D Language Foundation, All Rights Reserved * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright) * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/ast_node.d, _ast_node.d) diff --git a/dmd/ast_node.h b/dmd/ast_node.h index 6154c6d1b3a..a24218a86d0 100644 --- a/dmd/ast_node.h +++ b/dmd/ast_node.h @@ -1,6 +1,6 @@ /* Compiler implementation of the D programming language - * Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved + * Copyright (C) 1999-2024 by The D Language Foundation, All Rights Reserved * written by Walter Bright * https://www.digitalmars.com * Distributed under the Boost Software License, Version 1.0. diff --git a/dmd/astenums.d b/dmd/astenums.d index 4632959ac99..f19edb9e4b4 100644 --- a/dmd/astenums.d +++ b/dmd/astenums.d @@ -1,7 +1,7 @@ /** * Defines enums common to dmd and dmd as parse library. * - * Copyright: Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved + * Copyright: Copyright (C) 1999-2024 by The D Language Foundation, All Rights Reserved * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/astenums.d, _astenums.d) * Documentation: https://dlang.org/phobos/dmd_astenums.html diff --git a/dmd/asttypename.d b/dmd/asttypename.d index d853950e52a..da30c2f0e3d 100644 --- a/dmd/asttypename.d +++ b/dmd/asttypename.d @@ -1,7 +1,7 @@ /** * Development utility for printing AST nodes by their internal name, instead of as D source code. * - * Copyright: Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved + * Copyright: Copyright (C) 1999-2024 by The D Language Foundation, All Rights Reserved * Authors: Stefan Koch * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/asttypename.d, _asttypename.d) diff --git a/dmd/attrib.d b/dmd/attrib.d index f81dcf4701b..d7d3eca6f8d 100644 --- a/dmd/attrib.d +++ b/dmd/attrib.d @@ -14,7 +14,7 @@ * - Protection (`private`, `public`) * - Deprecated declarations (`@deprecated`) * - * Copyright: Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved + * Copyright: Copyright (C) 1999-2024 by The D Language Foundation, All Rights Reserved * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright) * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/attrib.d, _attrib.d) diff --git a/dmd/attrib.h b/dmd/attrib.h index 9b2340b9269..344a7e929a7 100644 --- a/dmd/attrib.h +++ b/dmd/attrib.h @@ -1,6 +1,6 @@ /* Compiler implementation of the D programming language - * Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved + * Copyright (C) 1999-2024 by The D Language Foundation, All Rights Reserved * written by Walter Bright * https://www.digitalmars.com * Distributed under the Boost Software License, Version 1.0. diff --git a/dmd/blockexit.d b/dmd/blockexit.d index 5108ecf7ba7..d77af7e1c5c 100644 --- a/dmd/blockexit.d +++ b/dmd/blockexit.d @@ -1,7 +1,7 @@ /** * Find out in what ways control flow can exit a statement block. * - * Copyright: Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved + * Copyright: Copyright (C) 1999-2024 by The D Language Foundation, All Rights Reserved * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright) * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/blockexit.d, _blockexit.d) diff --git a/dmd/builtin.d b/dmd/builtin.d index e64a96f373e..3e4b9e934a2 100644 --- a/dmd/builtin.d +++ b/dmd/builtin.d @@ -3,7 +3,7 @@ * * Currently includes functions from `std.math`, `core.math` and `core.bitop`. * - * Copyright: Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved + * Copyright: Copyright (C) 1999-2024 by The D Language Foundation, All Rights Reserved * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright) * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/builtin.d, _builtin.d) diff --git a/dmd/canthrow.d b/dmd/canthrow.d index 5a608a9986d..31155f188dc 100644 --- a/dmd/canthrow.d +++ b/dmd/canthrow.d @@ -3,7 +3,7 @@ * * Specification: $(LINK2 https://dlang.org/spec/function.html#nothrow-functions, Nothrow Functions) * - * Copyright: Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved + * Copyright: Copyright (C) 1999-2024 by The D Language Foundation, All Rights Reserved * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright) * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/canthrow.d, _canthrow.d) diff --git a/dmd/chkformat.d b/dmd/chkformat.d index 8cfad5916c7..5024f9bb210 100644 --- a/dmd/chkformat.d +++ b/dmd/chkformat.d @@ -1,7 +1,7 @@ /** * Check the arguments to `printf` and `scanf` against the `format` string. * - * Copyright: Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved + * Copyright: Copyright (C) 1999-2024 by The D Language Foundation, All Rights Reserved * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright) * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/chkformat.d, _chkformat.d) diff --git a/dmd/cli.d b/dmd/cli.d index ebfd9504a7f..35c49315b18 100644 --- a/dmd/cli.d +++ b/dmd/cli.d @@ -5,7 +5,7 @@ * However, this file will be used to generate the * $(LINK2 https://dlang.org/dmd-linux.html, online documentation) and MAN pages. * - * Copyright: Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved + * Copyright: Copyright (C) 1999-2024 by The D Language Foundation, All Rights Reserved * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright) * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/cli.d, _cli.d) diff --git a/dmd/clone.d b/dmd/clone.d index e4060d4e392..6fbf8e284de 100644 --- a/dmd/clone.d +++ b/dmd/clone.d @@ -2,7 +2,7 @@ * Builds struct member functions if needed and not defined by the user. * Includes `opEquals`, `opAssign`, post blit, copy constructor and destructor. * - * Copyright: Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved + * Copyright: Copyright (C) 1999-2024 by The D Language Foundation, All Rights Reserved * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright) * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/clone.d, _clone.d) diff --git a/dmd/common/bitfields.d b/dmd/common/bitfields.d index b9fcb0995c9..01aa56d1809 100644 --- a/dmd/common/bitfields.d +++ b/dmd/common/bitfields.d @@ -1,7 +1,7 @@ /** * A library bitfields utility * - * Copyright: Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved + * Copyright: Copyright (C) 1999-2024 by The D Language Foundation, All Rights Reserved * Authors: Dennis Korpel * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/common/bitfields.d, common/bitfields.d) diff --git a/dmd/common/file.d b/dmd/common/file.d index 704110f50bd..8a284241fc2 100644 --- a/dmd/common/file.d +++ b/dmd/common/file.d @@ -4,7 +4,7 @@ * Functions and objects dedicated to file I/O and management. TODO: Move here artifacts * from places such as root/ so both the frontend and the backend have access to them. * - * Copyright: Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved + * Copyright: Copyright (C) 1999-2024 by The D Language Foundation, All Rights Reserved * Authors: Walter Bright, https://www.digitalmars.com * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/common/file.d, common/_file.d) diff --git a/dmd/common/int128.d b/dmd/common/int128.d index a45af4254ef..796687b1f77 100644 --- a/dmd/common/int128.d +++ b/dmd/common/int128.d @@ -2,7 +2,7 @@ * * Not optimized for speed. * - * Copyright: Copyright D Language Foundation 2022. + * Copyright: Copyright (C) 2022-2024 by The D Language Foundation, All Rights Reserved * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) * Authors: Walter Bright * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/common/int128.d, root/_int128.d) diff --git a/dmd/common/outbuffer.d b/dmd/common/outbuffer.d index 4e7a82fb565..cff08ec5d43 100644 --- a/dmd/common/outbuffer.d +++ b/dmd/common/outbuffer.d @@ -1,7 +1,7 @@ /** * An expandable buffer in which you can write text or binary data. * - * Copyright: Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved + * Copyright: Copyright (C) 1999-2024 by The D Language Foundation, All Rights Reserved * Authors: Walter Bright, https://www.digitalmars.com * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/root/outbuffer.d, root/_outbuffer.d) diff --git a/dmd/common/outbuffer.h b/dmd/common/outbuffer.h index 4c1dceea3f6..2250497c38f 100644 --- a/dmd/common/outbuffer.h +++ b/dmd/common/outbuffer.h @@ -1,5 +1,5 @@ -/* Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved +/* Copyright (C) 1999-2024 by The D Language Foundation, All Rights Reserved * written by Walter Bright * https://www.digitalmars.com * Distributed under the Boost Software License, Version 1.0. diff --git a/dmd/common/smallbuffer.d b/dmd/common/smallbuffer.d index 83b67cdbb3d..c6aa7abbc60 100644 --- a/dmd/common/smallbuffer.d +++ b/dmd/common/smallbuffer.d @@ -1,7 +1,7 @@ /** * Common string functions including filename manipulation. * - * Copyright: Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved + * Copyright: Copyright (C) 1999-2024 by The D Language Foundation, All Rights Reserved * Authors: Walter Bright, https://www.digitalmars.com * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/common/smallbuffer.d, common/_smallbuffer.d) diff --git a/dmd/compiler.d b/dmd/compiler.d index 7ace90178b2..4c3f43d0382 100644 --- a/dmd/compiler.d +++ b/dmd/compiler.d @@ -1,7 +1,7 @@ /** * Describes a back-end compiler and implements compiler-specific actions. * - * Copyright: Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved + * Copyright: Copyright (C) 1999-2024 by The D Language Foundation, All Rights Reserved * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright) * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/compiler.d, _compiler.d) diff --git a/dmd/compiler.h b/dmd/compiler.h index c7cbce3bd7f..74351edb449 100644 --- a/dmd/compiler.h +++ b/dmd/compiler.h @@ -1,6 +1,6 @@ /* Compiler implementation of the D programming language - * Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved + * Copyright (C) 1999-2024 by The D Language Foundation, All Rights Reserved * written by Walter Bright * https://www.digitalmars.com * Distributed under the Boost Software License, Version 1.0. diff --git a/dmd/cond.d b/dmd/cond.d index 568b639e0b6..1b32ff774c8 100644 --- a/dmd/cond.d +++ b/dmd/cond.d @@ -3,7 +3,7 @@ * * Specification: $(LINK2 https://dlang.org/spec/version.html, Conditional Compilation) * - * Copyright: Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved + * Copyright: Copyright (C) 1999-2024 by The D Language Foundation, All Rights Reserved * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright) * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/cond.d, _cond.d) diff --git a/dmd/cond.h b/dmd/cond.h index d02ae1321c5..fe497c2da7e 100644 --- a/dmd/cond.h +++ b/dmd/cond.h @@ -1,6 +1,6 @@ /* Compiler implementation of the D programming language - * Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved + * Copyright (C) 1999-2024 by The D Language Foundation, All Rights Reserved * written by Walter Bright * https://www.digitalmars.com * Distributed under the Boost Software License, Version 1.0. diff --git a/dmd/console.d b/dmd/console.d index 3b834b6fe4b..a57348c89b5 100644 --- a/dmd/console.d +++ b/dmd/console.d @@ -2,7 +2,7 @@ * Control the various text mode attributes, such as color, when writing text * to the console. * - * Copyright: Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved + * Copyright: Copyright (C) 1999-2024 by The D Language Foundation, All Rights Reserved * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright) * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/console.d, _console.d) diff --git a/dmd/constfold.d b/dmd/constfold.d index fc3fd3b2486..7bd9691a429 100644 --- a/dmd/constfold.d +++ b/dmd/constfold.d @@ -5,7 +5,7 @@ * * Specification: $(LINK2 https://dlang.org/spec/float.html#fp_const_folding, Floating Point Constant Folding) * - * Copyright: Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved + * Copyright: Copyright (C) 1999-2024 by The D Language Foundation, All Rights Reserved * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright) * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/constfold.d, _constfold.d) diff --git a/dmd/cparse.d b/dmd/cparse.d index de85593a9e4..e0cdc87b7fd 100644 --- a/dmd/cparse.d +++ b/dmd/cparse.d @@ -3,7 +3,7 @@ * * Specification: C11 * - * Copyright: Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved + * Copyright: Copyright (C) 1999-2024 by The D Language Foundation, All Rights Reserved * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright) * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/cparse.d, _cparse.d) diff --git a/dmd/cppmangle.d b/dmd/cppmangle.d index 55844ddf606..90b6295ab2f 100644 --- a/dmd/cppmangle.d +++ b/dmd/cppmangle.d @@ -4,7 +4,7 @@ * This is the POSIX side of the implementation. * It exports two functions to C++, `toCppMangleItanium` and `cppTypeInfoMangleItanium`. * - * Copyright: Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved + * Copyright: Copyright (C) 1999-2024 by The D Language Foundation, All Rights Reserved * Authors: Walter Bright, https://www.digitalmars.com * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/cppmangle.d, _cppmangle.d) diff --git a/dmd/cppmanglewin.d b/dmd/cppmanglewin.d index e61ea0396de..4b96ac6add6 100644 --- a/dmd/cppmanglewin.d +++ b/dmd/cppmanglewin.d @@ -1,7 +1,7 @@ /** * Do mangling for C++ linkage for Digital Mars C++ and Microsoft Visual C++. * - * Copyright: Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved + * Copyright: Copyright (C) 1999-2024 by The D Language Foundation, All Rights Reserved * Authors: Walter Bright, https://www.digitalmars.com * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/cppmanglewin.d, _cppmanglewin.d) diff --git a/dmd/ctfe.h b/dmd/ctfe.h index bb92778e253..72d895c7150 100644 --- a/dmd/ctfe.h +++ b/dmd/ctfe.h @@ -1,6 +1,6 @@ /* Compiler implementation of the D programming language - * Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved + * Copyright (C) 1999-2024 by The D Language Foundation, All Rights Reserved * written by Walter Bright * https://www.digitalmars.com * Distributed under the Boost Software License, Version 1.0. diff --git a/dmd/ctfeexpr.d b/dmd/ctfeexpr.d index 993bab023f9..5fe1e7dccb0 100644 --- a/dmd/ctfeexpr.d +++ b/dmd/ctfeexpr.d @@ -1,7 +1,7 @@ /** * CTFE for expressions involving pointers, slices, array concatenation etc. * - * Copyright: Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved + * Copyright: Copyright (C) 1999-2024 by The D Language Foundation, All Rights Reserved * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright) * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/ctfeexpr.d, _ctfeexpr.d) diff --git a/dmd/ctorflow.d b/dmd/ctorflow.d index 128c698ab87..ba5240e5e10 100644 --- a/dmd/ctorflow.d +++ b/dmd/ctorflow.d @@ -1,7 +1,7 @@ /** * Manage flow analysis for constructors. * - * Copyright: Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved + * Copyright: Copyright (C) 1999-2024 by The D Language Foundation, All Rights Reserved * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright) * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/ctorflow.d, _ctorflow.d) diff --git a/dmd/dcast.d b/dmd/dcast.d index cfa374c970b..628c688979f 100644 --- a/dmd/dcast.d +++ b/dmd/dcast.d @@ -1,7 +1,7 @@ /** * Semantic analysis for cast-expressions. * - * Copyright: Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved + * Copyright: Copyright (C) 1999-2024 by The D Language Foundation, All Rights Reserved * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright) * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/dcast.d, _dcast.d) diff --git a/dmd/dclass.d b/dmd/dclass.d index e066d877e8a..405e8170b2c 100644 --- a/dmd/dclass.d +++ b/dmd/dclass.d @@ -3,7 +3,7 @@ * * Specification: $(LINK2 https://dlang.org/spec/class.html, Classes) * - * Copyright: Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved + * Copyright: Copyright (C) 1999-2024 by The D Language Foundation, All Rights Reserved * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright) * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/dclass.d, _dclass.d) diff --git a/dmd/declaration.d b/dmd/declaration.d index b357a63663a..5869a220842 100644 --- a/dmd/declaration.d +++ b/dmd/declaration.d @@ -2,7 +2,7 @@ * Miscellaneous declarations, including typedef, alias, variable declarations including the * implicit this declaration, type tuples, ClassInfo, ModuleInfo and various TypeInfos. * - * Copyright: Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved + * Copyright: Copyright (C) 1999-2024 by The D Language Foundation, All Rights Reserved * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright) * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/declaration.d, _declaration.d) diff --git a/dmd/declaration.h b/dmd/declaration.h index 484cf9feede..0e327bedfbd 100644 --- a/dmd/declaration.h +++ b/dmd/declaration.h @@ -1,6 +1,6 @@ /* Compiler implementation of the D programming language - * Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved + * Copyright (C) 1999-2024 by The D Language Foundation, All Rights Reserved * written by Walter Bright * https://www.digitalmars.com * Distributed under the Boost Software License, Version 1.0. diff --git a/dmd/delegatize.d b/dmd/delegatize.d index 490ef56646f..62800d3fdb7 100644 --- a/dmd/delegatize.d +++ b/dmd/delegatize.d @@ -3,7 +3,7 @@ * * Specification: $(LINK2 https://dlang.org/spec/function.html#lazy-params, Lazy Parameters) * - * Copyright: Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved + * Copyright: Copyright (C) 1999-2024 by The D Language Foundation, All Rights Reserved * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright) * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/delegatize.d, _delegatize.d) diff --git a/dmd/denum.d b/dmd/denum.d index e7a237ce0f9..5464ff99f58 100644 --- a/dmd/denum.d +++ b/dmd/denum.d @@ -3,7 +3,7 @@ * * Specification: $(LINK2 https://dlang.org/spec/enum.html, Enums) * - * Copyright: Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved + * Copyright: Copyright (C) 1999-2024 by The D Language Foundation, All Rights Reserved * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright) * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/denum.d, _denum.d) diff --git a/dmd/dimport.d b/dmd/dimport.d index 51b9220c185..b083c03aebe 100644 --- a/dmd/dimport.d +++ b/dmd/dimport.d @@ -1,7 +1,7 @@ /** * A `Dsymbol` representing a renamed import. * - * Copyright: Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved + * Copyright: Copyright (C) 1999-2024 by The D Language Foundation, All Rights Reserved * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright) * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/dimport.d, _dimport.d) diff --git a/dmd/dinterpret.d b/dmd/dinterpret.d index 90352e32bea..eda91d1ea05 100644 --- a/dmd/dinterpret.d +++ b/dmd/dinterpret.d @@ -3,7 +3,7 @@ * * Specification: ($LINK2 https://dlang.org/spec/function.html#interpretation, Compile Time Function Execution (CTFE)) * - * Copyright: Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved + * Copyright: Copyright (C) 1999-2024 by The D Language Foundation, All Rights Reserved * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright) * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/dinterpret.d, _dinterpret.d) diff --git a/dmd/dmacro.d b/dmd/dmacro.d index 6e6c4b17e99..c04fbec731d 100644 --- a/dmd/dmacro.d +++ b/dmd/dmacro.d @@ -1,7 +1,7 @@ /** * Text macro processor for Ddoc. * - * Copyright: Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved + * Copyright: Copyright (C) 1999-2024 by The D Language Foundation, All Rights Reserved * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright) * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/dmacro.d, _dmacro.d) diff --git a/dmd/dmangle.d b/dmd/dmangle.d index afd139ccb15..15b77eaac4c 100644 --- a/dmd/dmangle.d +++ b/dmd/dmangle.d @@ -3,7 +3,7 @@ * * Specification: $(LINK2 https://dlang.org/spec/abi.html#name_mangling, Name Mangling) * - * Copyright: Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved + * Copyright: Copyright (C) 1999-2024 by The D Language Foundation, All Rights Reserved * Authors: Walter Bright, https://www.digitalmars.com * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/dmangle.d, _dmangle.d) diff --git a/dmd/dmodule.d b/dmd/dmodule.d index 6c9e90a2c8f..022231c1254 100644 --- a/dmd/dmodule.d +++ b/dmd/dmodule.d @@ -3,7 +3,7 @@ * * Specification: $(LINK2 https://dlang.org/spec/module.html, Modules) * - * Copyright: Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved + * Copyright: Copyright (C) 1999-2024 by The D Language Foundation, All Rights Reserved * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright) * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/dmodule.d, _dmodule.d) diff --git a/dmd/doc.d b/dmd/doc.d index a154181aa3a..810642f9f52 100644 --- a/dmd/doc.d +++ b/dmd/doc.d @@ -3,7 +3,7 @@ * * Specification: $(LINK2 https://dlang.org/spec/ddoc.html, Documentation Generator) * - * Copyright: Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved + * Copyright: Copyright (C) 1999-2024 by The D Language Foundation, All Rights Reserved * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright) * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/doc.d, _doc.d) diff --git a/dmd/doc.h b/dmd/doc.h index ebd3094348d..71a66b90cb8 100644 --- a/dmd/doc.h +++ b/dmd/doc.h @@ -1,6 +1,6 @@ /* Compiler implementation of the D programming language - * Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved + * Copyright (C) 1999-2024 by The D Language Foundation, All Rights Reserved * written by Walter Bright * https://www.digitalmars.com * Distributed under the Boost Software License, Version 1.0. diff --git a/dmd/dscope.d b/dmd/dscope.d index cd177a66f50..7e9499fd28f 100644 --- a/dmd/dscope.d +++ b/dmd/dscope.d @@ -3,7 +3,7 @@ * * Not to be confused with the `scope` storage class. * - * Copyright: Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved + * Copyright: Copyright (C) 1999-2024 by The D Language Foundation, All Rights Reserved * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright) * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/dscope.d, _dscope.d) diff --git a/dmd/dstruct.d b/dmd/dstruct.d index 49411c69754..5683d5fb1d5 100644 --- a/dmd/dstruct.d +++ b/dmd/dstruct.d @@ -3,7 +3,7 @@ * * Specification: $(LINK2 https://dlang.org/spec/struct.html, Structs, Unions) * - * Copyright: Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved + * Copyright: Copyright (C) 1999-2024 by The D Language Foundation, All Rights Reserved * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright) * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/dstruct.d, _dstruct.d) diff --git a/dmd/dsymbol.d b/dmd/dsymbol.d index b4e3f433348..5e7922ea11d 100644 --- a/dmd/dsymbol.d +++ b/dmd/dsymbol.d @@ -1,7 +1,7 @@ /** * The base class for a D symbol, which can be a module, variable, function, enum, etc. * - * Copyright: Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved + * Copyright: Copyright (C) 1999-2024 by The D Language Foundation, All Rights Reserved * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright) * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/dsymbol.d, _dsymbol.d) diff --git a/dmd/dsymbol.h b/dmd/dsymbol.h index 0137edcf45c..7d715b47b31 100644 --- a/dmd/dsymbol.h +++ b/dmd/dsymbol.h @@ -1,6 +1,6 @@ /* Compiler implementation of the D programming language - * Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved + * Copyright (C) 1999-2024 by The D Language Foundation, All Rights Reserved * written by Walter Bright * https://www.digitalmars.com * Distributed under the Boost Software License, Version 1.0. diff --git a/dmd/dsymbolsem.d b/dmd/dsymbolsem.d index 62f3d698a12..23f0bc5b428 100644 --- a/dmd/dsymbolsem.d +++ b/dmd/dsymbolsem.d @@ -2,7 +2,7 @@ * Does the semantic 1 pass on the AST, which looks at symbol declarations but not initializers * or function bodies. * - * Copyright: Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved + * Copyright: Copyright (C) 1999-2024 by The D Language Foundation, All Rights Reserved * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright) * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/dsymbolsem.d, _dsymbolsem.d) diff --git a/dmd/dtemplate.d b/dmd/dtemplate.d index 82f0e57078a..1d84ccd0295 100644 --- a/dmd/dtemplate.d +++ b/dmd/dtemplate.d @@ -28,7 +28,7 @@ * arguments, and uses it if found. * - Otherwise, the rest of semantic is run on the `TemplateInstance`. * - * Copyright: Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved + * Copyright: Copyright (C) 1999-2024 by The D Language Foundation, All Rights Reserved * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright) * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/dtemplate.d, _dtemplate.d) diff --git a/dmd/dtoh.d b/dmd/dtoh.d index ed83a8d9fe1..30991c9171a 100644 --- a/dmd/dtoh.d +++ b/dmd/dtoh.d @@ -2,7 +2,7 @@ * This module contains the implementation of the C++ header generation available through * the command line switch -Hc. * - * Copyright: Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved + * Copyright: Copyright (C) 1999-2024 by The D Language Foundation, All Rights Reserved * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright) * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/dtohd, _dtoh.d) diff --git a/dmd/dversion.d b/dmd/dversion.d index 31725c80b9b..2e3b35264db 100644 --- a/dmd/dversion.d +++ b/dmd/dversion.d @@ -4,7 +4,7 @@ * Specification: $(LINK2 https://dlang.org/spec/version.html#version-specification, Version Specification), * $(LINK2 https://dlang.org/spec/version.html#debug_specification, Debug Specification). * - * Copyright: Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved + * Copyright: Copyright (C) 1999-2024 by The D Language Foundation, All Rights Reserved * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright) * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/dversion.d, _dversion.d) diff --git a/dmd/entity.d b/dmd/entity.d index c31883f11d9..af74c3bb8d5 100644 --- a/dmd/entity.d +++ b/dmd/entity.d @@ -3,7 +3,7 @@ * * Specification $(LINK2 https://dlang.org/spec/entity.html, Named Character Entities) * - * Copyright: Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved + * Copyright: Copyright (C) 1999-2024 by The D Language Foundation, All Rights Reserved * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright) * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/entity.d, _entity.d) diff --git a/dmd/enum.h b/dmd/enum.h index 740b6cb7e6c..a4bb588cac6 100644 --- a/dmd/enum.h +++ b/dmd/enum.h @@ -1,6 +1,6 @@ /* Compiler implementation of the D programming language - * Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved + * Copyright (C) 1999-2024 by The D Language Foundation, All Rights Reserved * written by Walter Bright * https://www.digitalmars.com * Distributed under the Boost Software License, Version 1.0. diff --git a/dmd/errors.d b/dmd/errors.d index 277818d9819..fe23c6eb415 100644 --- a/dmd/errors.d +++ b/dmd/errors.d @@ -1,7 +1,7 @@ /** * Functions for raising errors. * - * Copyright: Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved + * Copyright: Copyright (C) 1999-2024 by The D Language Foundation, All Rights Reserved * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright) * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/errors.d, _errors.d) diff --git a/dmd/errors.h b/dmd/errors.h index 759ad277fda..308e81e30ba 100644 --- a/dmd/errors.h +++ b/dmd/errors.h @@ -1,6 +1,6 @@ /* Compiler implementation of the D programming language - * Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved + * Copyright (C) 1999-2024 by The D Language Foundation, All Rights Reserved * written by Walter Bright * https://www.digitalmars.com * Distributed under the Boost Software License, Version 1.0. diff --git a/dmd/errorsink.d b/dmd/errorsink.d index 3811f1d2932..afea689546b 100644 --- a/dmd/errorsink.d +++ b/dmd/errorsink.d @@ -1,7 +1,7 @@ /** * Provides an abstraction for what to do with error messages. * - * Copyright: Copyright (C) 2023 by The D Language Foundation, All Rights Reserved + * Copyright: Copyright (C) 2023-2024 by The D Language Foundation, All Rights Reserved * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright) * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/errorsink.d, _errorsink.d) diff --git a/dmd/escape.d b/dmd/escape.d index be171158275..433907a17be 100644 --- a/dmd/escape.d +++ b/dmd/escape.d @@ -1,7 +1,7 @@ /** * Most of the logic to implement scoped pointers and scoped references is here. * - * Copyright: Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved + * Copyright: Copyright (C) 1999-2024 by The D Language Foundation, All Rights Reserved * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright) * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/escape.d, _escape.d) diff --git a/dmd/expression.d b/dmd/expression.d index ea12a73ae46..41eeff923d8 100644 --- a/dmd/expression.d +++ b/dmd/expression.d @@ -3,7 +3,7 @@ * * Specification: ($LINK2 https://dlang.org/spec/expression.html, Expressions) * - * Copyright: Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved + * Copyright: Copyright (C) 1999-2024 by The D Language Foundation, All Rights Reserved * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright) * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/expression.d, _expression.d) diff --git a/dmd/expression.h b/dmd/expression.h index f757c15c28e..f57f6a40295 100644 --- a/dmd/expression.h +++ b/dmd/expression.h @@ -1,6 +1,6 @@ /* Compiler implementation of the D programming language - * Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved + * Copyright (C) 1999-2024 by The D Language Foundation, All Rights Reserved * written by Walter Bright * https://www.digitalmars.com * Distributed under the Boost Software License, Version 1.0. diff --git a/dmd/expressionsem.d b/dmd/expressionsem.d index f9bf70cfa1a..9ce6f4ded9d 100644 --- a/dmd/expressionsem.d +++ b/dmd/expressionsem.d @@ -3,7 +3,7 @@ * * Specification: ($LINK2 https://dlang.org/spec/expression.html, Expressions) * - * Copyright: Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved + * Copyright: Copyright (C) 1999-2024 by The D Language Foundation, All Rights Reserved * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright) * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/expressionsem.d, _expressionsem.d) diff --git a/dmd/file_manager.d b/dmd/file_manager.d index 0ea78b5f954..eaef8d545e6 100644 --- a/dmd/file_manager.d +++ b/dmd/file_manager.d @@ -1,7 +1,7 @@ /** * Read a file from disk and store it in memory. * - * Copyright: Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved + * Copyright: Copyright (C) 1999-2024 by The D Language Foundation, All Rights Reserved * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/file_manager.d, _file_manager.d) * Documentation: https://dlang.org/phobos/dmd_file_manager.html diff --git a/dmd/foreachvar.d b/dmd/foreachvar.d index dc4b20bf957..53b3c041d1e 100644 --- a/dmd/foreachvar.d +++ b/dmd/foreachvar.d @@ -1,7 +1,7 @@ /** * Utility to visit every variable in an expression. * - * Copyright: Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved + * Copyright: Copyright (C) 1999-2024 by The D Language Foundation, All Rights Reserved * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright) * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/foreachvar.d, _foreachvar.d) diff --git a/dmd/frontend.h b/dmd/frontend.h index 64296ec8262..7392c7ee940 100644 --- a/dmd/frontend.h +++ b/dmd/frontend.h @@ -8385,7 +8385,7 @@ struct Global final const char* const versionChars(); Global() : inifilename(), - copyright(73, "Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved"), + copyright(73, "Copyright (C) 1999-2024 by The D Language Foundation, All Rights Reserved"), written(24, "written by Walter Bright"), path(), filePath(), @@ -8407,7 +8407,7 @@ struct Global final preprocess() { } - Global(_d_dynamicArray< const char > inifilename, _d_dynamicArray< const char > copyright = { 73, "Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved" }, _d_dynamicArray< const char > written = { 24, "written by Walter Bright" }, Array* path = nullptr, Array* filePath = nullptr, CompileEnv compileEnv = CompileEnv(), Param params = Param(), uint32_t errors = 0u, uint32_t warnings = 0u, uint32_t gag = 0u, uint32_t gaggedErrors = 0u, uint32_t gaggedWarnings = 0u, void* console = nullptr, Array* versionids = nullptr, Array* debugids = nullptr, bool hasMainFunction = false, uint32_t varSequenceNumber = 1u, FileManager* fileManager = nullptr, ErrorSink* errorSink = nullptr, ErrorSink* errorSinkNull = nullptr, FileName(*preprocess)(FileName , const Loc& , bool& , OutBuffer* ) = nullptr) : + Global(_d_dynamicArray< const char > inifilename, _d_dynamicArray< const char > copyright = { 73, "Copyright (C) 1999-2024 by The D Language Foundation, All Rights Reserved" }, _d_dynamicArray< const char > written = { 24, "written by Walter Bright" }, Array* path = nullptr, Array* filePath = nullptr, CompileEnv compileEnv = CompileEnv(), Param params = Param(), uint32_t errors = 0u, uint32_t warnings = 0u, uint32_t gag = 0u, uint32_t gaggedErrors = 0u, uint32_t gaggedWarnings = 0u, void* console = nullptr, Array* versionids = nullptr, Array* debugids = nullptr, bool hasMainFunction = false, uint32_t varSequenceNumber = 1u, FileManager* fileManager = nullptr, ErrorSink* errorSink = nullptr, ErrorSink* errorSinkNull = nullptr, FileName(*preprocess)(FileName , const Loc& , bool& , OutBuffer* ) = nullptr) : inifilename(inifilename), copyright(copyright), written(written), diff --git a/dmd/func.d b/dmd/func.d index 0889ea26a97..242b4dc99f9 100644 --- a/dmd/func.d +++ b/dmd/func.d @@ -8,7 +8,7 @@ * - `invariant` * - `unittest` * - * Copyright: Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved + * Copyright: Copyright (C) 1999-2024 by The D Language Foundation, All Rights Reserved * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright) * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/func.d, _func.d) diff --git a/dmd/globals.d b/dmd/globals.d index 9257bc464f4..b60a3f8cad1 100644 --- a/dmd/globals.d +++ b/dmd/globals.d @@ -1,7 +1,7 @@ /** * Stores command line options and contains other miscellaneous declarations. * - * Copyright: Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved + * Copyright: Copyright (C) 1999-2024 by The D Language Foundation, All Rights Reserved * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright) * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/globals.d, _globals.d) @@ -275,7 +275,7 @@ extern (C++) struct Global { const(char)[] inifilename; /// filename of configuration file as given by `-conf=`, or default value - string copyright = "Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved"; + string copyright = "Copyright (C) 1999-2024 by The D Language Foundation, All Rights Reserved"; string written = "written by Walter Bright"; Array!(const(char)*)* path; /// Array of char*'s which form the import lookup path diff --git a/dmd/globals.h b/dmd/globals.h index 4284f858466..c71d2f0499d 100644 --- a/dmd/globals.h +++ b/dmd/globals.h @@ -1,6 +1,6 @@ /* Compiler implementation of the D programming language - * Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved + * Copyright (C) 1999-2024 by The D Language Foundation, All Rights Reserved * written by Walter Bright * https://www.digitalmars.com * Distributed under the Boost Software License, Version 1.0. diff --git a/dmd/gluelayer.d b/dmd/gluelayer.d index 756c0e523f9..b3980eb7930 100644 --- a/dmd/gluelayer.d +++ b/dmd/gluelayer.d @@ -3,7 +3,7 @@ * * This 'glues' either the DMC or GCC back-end to the front-end. * - * Copyright: Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved + * Copyright: Copyright (C) 1999-2024 by The D Language Foundation, All Rights Reserved * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright) * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/gluelayer.d, _gluelayer.d) diff --git a/dmd/hdrgen.d b/dmd/hdrgen.d index 2eef70d6ce6..570c662624c 100644 --- a/dmd/hdrgen.d +++ b/dmd/hdrgen.d @@ -3,7 +3,7 @@ * * Also used to convert AST nodes to D code in general, e.g. for error messages or `printf` debugging. * - * Copyright: Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved + * Copyright: Copyright (C) 1999-2024 by The D Language Foundation, All Rights Reserved * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright) * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/hdrgen.d, _hdrgen.d) diff --git a/dmd/hdrgen.h b/dmd/hdrgen.h index fb5fbadae36..e38ca569354 100644 --- a/dmd/hdrgen.h +++ b/dmd/hdrgen.h @@ -1,6 +1,6 @@ /* Compiler implementation of the D programming language - * Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved + * Copyright (C) 1999-2024 by The D Language Foundation, All Rights Reserved * written by Dave Fladebo * https://www.digitalmars.com * Distributed under the Boost Software License, Version 1.0. diff --git a/dmd/iasmgcc.d b/dmd/iasmgcc.d index 92837b45842..db51e734155 100644 --- a/dmd/iasmgcc.d +++ b/dmd/iasmgcc.d @@ -1,7 +1,7 @@ /** * Inline assembler for the GCC D compiler. * - * Copyright (C) 2018-2023 by The D Language Foundation, All Rights Reserved + * Copyright (C) 2018-2024 by The D Language Foundation, All Rights Reserved * Authors: Iain Buclaw * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/iasmgcc.d, _iasmgcc.d) diff --git a/dmd/id.d b/dmd/id.d index d639b70141e..a66f2af4678 100644 --- a/dmd/id.d +++ b/dmd/id.d @@ -1,7 +1,7 @@ /** * Contains the `Id` struct with a list of predefined symbols the compiler knows about. * - * Copyright: Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved + * Copyright: Copyright (C) 1999-2024 by The D Language Foundation, All Rights Reserved * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright) * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/id.d, _id.d) diff --git a/dmd/id.h b/dmd/id.h index f6cf6e59c34..ddc8da23a8f 100644 --- a/dmd/id.h +++ b/dmd/id.h @@ -1,6 +1,6 @@ /* Compiler implementation of the D programming language - * Copyright (C) 2017-2023 by The D Language Foundation, All Rights Reserved + * Copyright (C) 2017-2024 by The D Language Foundation, All Rights Reserved * written by Walter Bright * https://www.digitalmars.com * Distributed under the Boost Software License, Version 1.0. diff --git a/dmd/identifier.d b/dmd/identifier.d index c2b2fbafa25..8ace310937d 100644 --- a/dmd/identifier.d +++ b/dmd/identifier.d @@ -1,7 +1,7 @@ /** * Defines an identifier, which is the name of a `Dsymbol`. * - * Copyright: Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved + * Copyright: Copyright (C) 1999-2024 by The D Language Foundation, All Rights Reserved * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright) * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/identifier.d, _identifier.d) diff --git a/dmd/identifier.h b/dmd/identifier.h index e7b3ba60b0f..afd3664bfa8 100644 --- a/dmd/identifier.h +++ b/dmd/identifier.h @@ -1,6 +1,6 @@ /* Compiler implementation of the D programming language - * Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved + * Copyright (C) 1999-2024 by The D Language Foundation, All Rights Reserved * written by Walter Bright * https://www.digitalmars.com * Distributed under the Boost Software License, Version 1.0. diff --git a/dmd/impcnvtab.d b/dmd/impcnvtab.d index b45880a2887..b899f810aab 100644 --- a/dmd/impcnvtab.d +++ b/dmd/impcnvtab.d @@ -6,7 +6,7 @@ * Specification: $(LINK2 https://dlang.org/spec/type.html#integer-promotions, Integer Promotions), * $(LINK2 https://dlang.org/spec/type.html#usual-arithmetic-conversions, Usual Arithmetic Conversions). * - * Copyright: Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved + * Copyright: Copyright (C) 1999-2024 by The D Language Foundation, All Rights Reserved * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright) * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/impcnvtab.d, _impcnvtab.d) diff --git a/dmd/imphint.d b/dmd/imphint.d index 9e9466a38eb..ea2f13d9179 100644 --- a/dmd/imphint.d +++ b/dmd/imphint.d @@ -3,7 +3,7 @@ * * For example, prompt to `import std.stdio` when using `writeln`. * - * Copyright: Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved + * Copyright: Copyright (C) 1999-2024 by The D Language Foundation, All Rights Reserved * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright) * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/imphint.d, _imphint.d) diff --git a/dmd/import.h b/dmd/import.h index 2a02f13ba55..bfbb5510134 100644 --- a/dmd/import.h +++ b/dmd/import.h @@ -1,6 +1,6 @@ /* Compiler implementation of the D programming language - * Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved + * Copyright (C) 1999-2024 by The D Language Foundation, All Rights Reserved * written by Walter Bright * https://www.digitalmars.com * Distributed under the Boost Software License, Version 1.0. diff --git a/dmd/importc.d b/dmd/importc.d index 2c7699b45ec..69a85ceec93 100644 --- a/dmd/importc.d +++ b/dmd/importc.d @@ -3,7 +3,7 @@ * * Specification: C11 * - * Copyright: Copyright (C) 2021-2023 by The D Language Foundation, All Rights Reserved + * Copyright: Copyright (C) 2021-2024 by The D Language Foundation, All Rights Reserved * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright) * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/importc.d, _importc.d) diff --git a/dmd/init.d b/dmd/init.d index 5aefb0048a6..62bd41eea93 100644 --- a/dmd/init.d +++ b/dmd/init.d @@ -1,7 +1,7 @@ /** * Defines initializers of variables, e.g. the array literal in `int[3] x = [0, 1, 2]`. * - * Copyright: Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved + * Copyright: Copyright (C) 1999-2024 by The D Language Foundation, All Rights Reserved * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright) * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/init.d, _init.d) diff --git a/dmd/init.h b/dmd/init.h index 21bd07f4f39..b4e15e3fa98 100644 --- a/dmd/init.h +++ b/dmd/init.h @@ -1,6 +1,6 @@ /* Compiler implementation of the D programming language - * Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved + * Copyright (C) 1999-2024 by The D Language Foundation, All Rights Reserved * written by Walter Bright * https://www.digitalmars.com * Distributed under the Boost Software License, Version 1.0. diff --git a/dmd/initsem.d b/dmd/initsem.d index 19d576d4660..5fe3b932599 100644 --- a/dmd/initsem.d +++ b/dmd/initsem.d @@ -1,7 +1,7 @@ /** * Semantic analysis of initializers. * - * Copyright: Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved + * Copyright: Copyright (C) 1999-2024 by The D Language Foundation, All Rights Reserved * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright) * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/initsem.d, _initsem.d) diff --git a/dmd/inline.d b/dmd/inline.d index 4dc87a5565a..21ca018072e 100644 --- a/dmd/inline.d +++ b/dmd/inline.d @@ -4,7 +4,7 @@ * The AST is traversed, and every function call is considered for inlining using `inlinecost.d`. * The function call is then inlined if this cost is below a threshold. * - * Copyright: Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved + * Copyright: Copyright (C) 1999-2024 by The D Language Foundation, All Rights Reserved * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright) * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/inline.d, _inline.d) diff --git a/dmd/inlinecost.d b/dmd/inlinecost.d index 0bfc5767927..99df897f320 100644 --- a/dmd/inlinecost.d +++ b/dmd/inlinecost.d @@ -1,7 +1,7 @@ /** * Compute the cost of inlining a function call by counting expressions. * - * Copyright: Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved + * Copyright: Copyright (C) 1999-2024 by The D Language Foundation, All Rights Reserved * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright) * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/inlinecost.d, _inlinecost.d) diff --git a/dmd/intrange.d b/dmd/intrange.d index 442668f6337..29c8b505cde 100644 --- a/dmd/intrange.d +++ b/dmd/intrange.d @@ -1,7 +1,7 @@ /** * Implement $(LINK2 https://digitalmars.com/articles/b62.html, Value Range Propagation). * - * Copyright: Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved + * Copyright: Copyright (C) 1999-2024 by The D Language Foundation, All Rights Reserved * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright) * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/intrange.d, _intrange.d) diff --git a/dmd/json.d b/dmd/json.d index 11ab8169099..9819c3a90cc 100644 --- a/dmd/json.d +++ b/dmd/json.d @@ -1,7 +1,7 @@ /** * Code for generating .json descriptions of the module when passing the `-X` flag to dmd. * - * Copyright: Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved + * Copyright: Copyright (C) 1999-2024 by The D Language Foundation, All Rights Reserved * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright) * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/json.d, _json.d) diff --git a/dmd/json.h b/dmd/json.h index 09fdecdb9ee..8a949114feb 100644 --- a/dmd/json.h +++ b/dmd/json.h @@ -1,6 +1,6 @@ /* Compiler implementation of the D programming language - * Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved + * Copyright (C) 1999-2024 by The D Language Foundation, All Rights Reserved * written by Walter Bright * https://www.digitalmars.com * Distributed under the Boost Software License, Version 1.0. diff --git a/dmd/lambdacomp.d b/dmd/lambdacomp.d index c90c36069fd..a1db8d52548 100644 --- a/dmd/lambdacomp.d +++ b/dmd/lambdacomp.d @@ -5,7 +5,7 @@ * The serialization is a string which contains the type of the parameters and the string * represantation of the lambda expression. * - * Copyright: Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved + * Copyright: Copyright (C) 1999-2024 by The D Language Foundation, All Rights Reserved * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright) * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/lamdbacomp.d, _lambdacomp.d) diff --git a/dmd/lexer.d b/dmd/lexer.d index 2c6a5950569..5eadd721f64 100644 --- a/dmd/lexer.d +++ b/dmd/lexer.d @@ -3,7 +3,7 @@ * * Specification: $(LINK2 https://dlang.org/spec/lex.html, Lexical) * - * Copyright: Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved + * Copyright: Copyright (C) 1999-2024 by The D Language Foundation, All Rights Reserved * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright) * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/lexer.d, _lexer.d) diff --git a/dmd/location.d b/dmd/location.d index 9fe48b88844..d71ea588c91 100644 --- a/dmd/location.d +++ b/dmd/location.d @@ -1,7 +1,7 @@ /** * Encapsulates file/line/column locations. * - * Copyright: Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved + * Copyright: Copyright (C) 1999-2024 by The D Language Foundation, All Rights Reserved * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright) * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/location.d, _location.d) diff --git a/dmd/main.d b/dmd/main.d index 27f86bdb4a9..68c6623e1ce 100644 --- a/dmd/main.d +++ b/dmd/main.d @@ -6,7 +6,7 @@ * utilities needed for arguments parsing, path manipulation, etc... * This file is not shared with other compilers which use the DMD front-end. * - * Copyright: Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved + * Copyright: Copyright (C) 1999-2024 by The D Language Foundation, All Rights Reserved * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright) * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/main.d, _main.d) diff --git a/dmd/mangle.h b/dmd/mangle.h index aa246988f2e..68064a9210a 100644 --- a/dmd/mangle.h +++ b/dmd/mangle.h @@ -1,6 +1,6 @@ /* Compiler implementation of the D programming language - * Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved + * Copyright (C) 1999-2024 by The D Language Foundation, All Rights Reserved * written by Walter Bright * https://www.digitalmars.com * Distributed under the Boost Software License, Version 1.0. diff --git a/dmd/mars.d b/dmd/mars.d index 1aa01e379d2..c78d32642cd 100644 --- a/dmd/mars.d +++ b/dmd/mars.d @@ -4,7 +4,7 @@ * utilities needed for arguments parsing, path manipulation, etc... * This file is not shared with other compilers which use the DMD front-end. * - * Copyright: Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved + * Copyright: Copyright (C) 1999-2024 by The D Language Foundation, All Rights Reserved * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright) * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/mars.d, _mars.d) diff --git a/dmd/module.h b/dmd/module.h index 80a6ea25965..d09e873c495 100644 --- a/dmd/module.h +++ b/dmd/module.h @@ -1,6 +1,6 @@ /* Compiler implementation of the D programming language - * Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved + * Copyright (C) 1999-2024 by The D Language Foundation, All Rights Reserved * written by Walter Bright * https://www.digitalmars.com * Distributed under the Boost Software License, Version 1.0. diff --git a/dmd/mtype.d b/dmd/mtype.d index 6a3e43ddf73..4c741cdd5cc 100644 --- a/dmd/mtype.d +++ b/dmd/mtype.d @@ -1,7 +1,7 @@ /** * Defines a D type. * - * Copyright: Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved + * Copyright: Copyright (C) 1999-2024 by The D Language Foundation, All Rights Reserved * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright) * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/mtype.d, _mtype.d) diff --git a/dmd/mtype.h b/dmd/mtype.h index c6eacc29878..97a7ae3c5af 100644 --- a/dmd/mtype.h +++ b/dmd/mtype.h @@ -1,6 +1,6 @@ /* Compiler implementation of the D programming language - * Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved + * Copyright (C) 1999-2024 by The D Language Foundation, All Rights Reserved * written by Walter Bright * https://www.digitalmars.com * Distributed under the Boost Software License, Version 1.0. diff --git a/dmd/mustuse.d b/dmd/mustuse.d index 83b63042cb7..b5601a214dc 100644 --- a/dmd/mustuse.d +++ b/dmd/mustuse.d @@ -1,7 +1,7 @@ /** * Compile-time checks associated with the @mustuse attribute. * - * Copyright: Copyright (C) 2022-2023 by The D Language Foundation, All Rights Reserved + * Copyright: Copyright (C) 2022-2024 by The D Language Foundation, All Rights Reserved * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/mustuse.d, _mustuse.d) * Documentation: https://dlang.org/phobos/dmd_mustuse.html diff --git a/dmd/nogc.d b/dmd/nogc.d index e59b01019f4..9e45e4549ff 100644 --- a/dmd/nogc.d +++ b/dmd/nogc.d @@ -3,7 +3,7 @@ * * Specification: $(LINK2 https://dlang.org/spec/function.html#nogc-functions, No-GC Functions) * - * Copyright: Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved + * Copyright: Copyright (C) 1999-2024 by The D Language Foundation, All Rights Reserved * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright) * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/nogc.d, _nogc.d) diff --git a/dmd/nspace.d b/dmd/nspace.d index 65f7d2964cb..52c2b79a4e5 100644 --- a/dmd/nspace.d +++ b/dmd/nspace.d @@ -36,7 +36,7 @@ * are valid D identifier. * * See_Also: https://github.com/dlang/dmd/pull/10031 - * Copyright: Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved + * Copyright: Copyright (C) 1999-2024 by The D Language Foundation, All Rights Reserved * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright) * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/nspace.d, _nspace.d) diff --git a/dmd/nspace.h b/dmd/nspace.h index 4a1bd9141ec..cbee2fb7914 100644 --- a/dmd/nspace.h +++ b/dmd/nspace.h @@ -1,6 +1,6 @@ /* Compiler implementation of the D programming language - * Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved + * Copyright (C) 1999-2024 by The D Language Foundation, All Rights Reserved * written by Walter Bright * https://www.digitalmars.com * Distributed under the Boost Software License, Version 1.0. diff --git a/dmd/ob.d b/dmd/ob.d index 51a141089d2..785912e1968 100644 --- a/dmd/ob.d +++ b/dmd/ob.d @@ -1,7 +1,7 @@ /** * Flow analysis for Ownership/Borrowing * - * Copyright: Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved + * Copyright: Copyright (C) 1999-2024 by The D Language Foundation, All Rights Reserved * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright) * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/ob.d, _ob.d) diff --git a/dmd/objc.d b/dmd/objc.d index 359474c588a..2f36d5d13da 100644 --- a/dmd/objc.d +++ b/dmd/objc.d @@ -3,7 +3,7 @@ * * Specification: $(LINK2 https://dlang.org/spec/objc_interface.html, Interfacing to Objective-C) * - * Copyright: Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved + * Copyright: Copyright (C) 1999-2024 by The D Language Foundation, All Rights Reserved * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright) * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/objc.d, _objc.d) diff --git a/dmd/objc.h b/dmd/objc.h index 40f634e9122..0390115aeb1 100644 --- a/dmd/objc.h +++ b/dmd/objc.h @@ -1,6 +1,6 @@ /* Compiler implementation of the D programming language - * Copyright (C) 2015-2023 by The D Language Foundation, All Rights Reserved + * Copyright (C) 2015-2024 by The D Language Foundation, All Rights Reserved * written by Michel Fortin * https://www.digitalmars.com * Distributed under the Boost Software License, Version 1.0. diff --git a/dmd/opover.d b/dmd/opover.d index b7bc9257b3e..d596b8487f2 100644 --- a/dmd/opover.d +++ b/dmd/opover.d @@ -3,7 +3,7 @@ * * Specification: $(LINK2 https://dlang.org/spec/operatoroverloading.html, Operator Overloading) * - * Copyright: Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved + * Copyright: Copyright (C) 1999-2024 by The D Language Foundation, All Rights Reserved * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright) * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/opover.d, _opover.d) diff --git a/dmd/optimize.d b/dmd/optimize.d index a9791684df4..f86abde5c3e 100644 --- a/dmd/optimize.d +++ b/dmd/optimize.d @@ -1,7 +1,7 @@ /** * Perform constant folding. * - * Copyright: Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved + * Copyright: Copyright (C) 1999-2024 by The D Language Foundation, All Rights Reserved * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright) * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/optimize.d, _optimize.d) diff --git a/dmd/parse.d b/dmd/parse.d index 2797a778bfd..a012e0c7c5b 100644 --- a/dmd/parse.d +++ b/dmd/parse.d @@ -3,7 +3,7 @@ * * Specification: $(LINK2 https://dlang.org/spec/grammar.html, D Grammar) * - * Copyright: Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved + * Copyright: Copyright (C) 1999-2024 by The D Language Foundation, All Rights Reserved * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright) * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/parse.d, _parse.d) diff --git a/dmd/postordervisitor.d b/dmd/postordervisitor.d index 70bd1300feb..fe189d47e94 100644 --- a/dmd/postordervisitor.d +++ b/dmd/postordervisitor.d @@ -1,7 +1,7 @@ /** * A depth-first visitor for expressions. * - * Copyright: Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved + * Copyright: Copyright (C) 1999-2024 by The D Language Foundation, All Rights Reserved * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright) * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/apply.d, _apply.d) diff --git a/dmd/printast.d b/dmd/printast.d index e1deb2c8786..02dc65390b0 100644 --- a/dmd/printast.d +++ b/dmd/printast.d @@ -1,7 +1,7 @@ /** * Provides an AST printer for debugging. * - * Copyright: Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved + * Copyright: Copyright (C) 1999-2024 by The D Language Foundation, All Rights Reserved * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright) * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/printast.d, _printast.d) diff --git a/dmd/root/aav.d b/dmd/root/aav.d index 1d450505a4d..8929679e37e 100644 --- a/dmd/root/aav.d +++ b/dmd/root/aav.d @@ -1,7 +1,7 @@ /** * Associative array implementation. * - * Copyright: Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved + * Copyright: Copyright (C) 1999-2024 by The D Language Foundation, All Rights Reserved * Authors: Walter Bright, https://www.digitalmars.com * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/root/aav.d, root/_aav.d) diff --git a/dmd/root/array.d b/dmd/root/array.d index f36ddb4f29e..81355774de3 100644 --- a/dmd/root/array.d +++ b/dmd/root/array.d @@ -2,7 +2,7 @@ /** * Dynamic array implementation. * - * Copyright: Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved + * Copyright: Copyright (C) 1999-2024 by The D Language Foundation, All Rights Reserved * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright) * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/root/array.d, root/_array.d) diff --git a/dmd/root/array.h b/dmd/root/array.h index ebe2c47d0a0..1033b22237a 100644 --- a/dmd/root/array.h +++ b/dmd/root/array.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2011-2023 by The D Language Foundation, All Rights Reserved +/* Copyright (C) 2011-2024 by The D Language Foundation, All Rights Reserved * written by Walter Bright * https://www.digitalmars.com * Distributed under the Boost Software License, Version 1.0. diff --git a/dmd/root/bitarray.d b/dmd/root/bitarray.d index 66adab65877..c32d59eec36 100644 --- a/dmd/root/bitarray.d +++ b/dmd/root/bitarray.d @@ -1,7 +1,7 @@ /** * Implementation of a bit array. * - * Copyright: Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved + * Copyright: Copyright (C) 1999-2024 by The D Language Foundation, All Rights Reserved * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright) * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/root/bitarray.d, root/_bitarray.d) diff --git a/dmd/root/bitarray.h b/dmd/root/bitarray.h index 617cc9e2cfa..2cd7152f725 100644 --- a/dmd/root/bitarray.h +++ b/dmd/root/bitarray.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2011-2023 by The D Language Foundation, All Rights Reserved +/* Copyright (C) 2011-2024 by The D Language Foundation, All Rights Reserved * written by Walter Bright * https://www.digitalmars.com * Distributed under the Boost Software License, Version 1.0. diff --git a/dmd/root/complex.d b/dmd/root/complex.d index 57d1e340eff..de4c8d34678 100644 --- a/dmd/root/complex.d +++ b/dmd/root/complex.d @@ -1,7 +1,7 @@ /** * Implements a complex number type. * - * Copyright: Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved + * Copyright: Copyright (C) 1999-2024 by The D Language Foundation, All Rights Reserved * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright) * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/root/complex.d, _complex.d) diff --git a/dmd/root/complex_t.h b/dmd/root/complex_t.h index de2040b88f7..8134f9e2591 100644 --- a/dmd/root/complex_t.h +++ b/dmd/root/complex_t.h @@ -1,6 +1,6 @@ /* Compiler implementation of the D programming language - * Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved + * Copyright (C) 1999-2024 by The D Language Foundation, All Rights Reserved * written by Walter Bright * https://www.digitalmars.com * Distributed under the Boost Software License, Version 1.0. diff --git a/dmd/root/ctfloat.d b/dmd/root/ctfloat.d index df1a20606a4..44e2fc02a45 100644 --- a/dmd/root/ctfloat.d +++ b/dmd/root/ctfloat.d @@ -1,7 +1,7 @@ /** * Collects functions for compile-time floating-point calculations. * - * Copyright: Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved + * Copyright: Copyright (C) 1999-2024 by The D Language Foundation, All Rights Reserved * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright) * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/root/ctfloat.d, root/_ctfloat.d) diff --git a/dmd/root/ctfloat.h b/dmd/root/ctfloat.h index d2f795bf9e9..ba8b4478246 100644 --- a/dmd/root/ctfloat.h +++ b/dmd/root/ctfloat.h @@ -1,5 +1,5 @@ -/* Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved +/* Copyright (C) 1999-2024 by The D Language Foundation, All Rights Reserved * written by Walter Bright * https://www.digitalmars.com * Distributed under the Boost Software License, Version 1.0. diff --git a/dmd/root/dcompat.h b/dmd/root/dcompat.h index 1a496880100..db2b2c6abcd 100644 --- a/dmd/root/dcompat.h +++ b/dmd/root/dcompat.h @@ -1,5 +1,5 @@ -/* Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved +/* Copyright (C) 1999-2024 by The D Language Foundation, All Rights Reserved * written by Walter Bright * https://www.digitalmars.com * Distributed under the Boost Software License, Version 1.0. diff --git a/dmd/root/dsystem.h b/dmd/root/dsystem.h index c0634d66bb5..76cb6ea875e 100644 --- a/dmd/root/dsystem.h +++ b/dmd/root/dsystem.h @@ -1,6 +1,6 @@ /* Compiler implementation of the D programming language - * Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved + * Copyright (C) 1999-2024 by The D Language Foundation, All Rights Reserved * written by Walter Bright * https://www.digitalmars.com * Distributed under the Boost Software License, Version 1.0. diff --git a/dmd/root/file.d b/dmd/root/file.d index fdf13d4e8b0..a4362e17178 100644 --- a/dmd/root/file.d +++ b/dmd/root/file.d @@ -1,7 +1,7 @@ /** * Read a file from disk and store it in memory. * - * Copyright: Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved + * Copyright: Copyright (C) 1999-2024 by The D Language Foundation, All Rights Reserved * Authors: Walter Bright, https://www.digitalmars.com * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/root/file.d, root/_file.d) diff --git a/dmd/root/filename.d b/dmd/root/filename.d index 8f31f212048..5b0bba42fc2 100644 --- a/dmd/root/filename.d +++ b/dmd/root/filename.d @@ -1,7 +1,7 @@ /** * Encapsulate path and file names. * - * Copyright: Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved + * Copyright: Copyright (C) 1999-2024 by The D Language Foundation, All Rights Reserved * Authors: Walter Bright, https://www.digitalmars.com * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/root/filename.d, root/_filename.d) diff --git a/dmd/root/filename.h b/dmd/root/filename.h index 62142331013..d8834a19282 100644 --- a/dmd/root/filename.h +++ b/dmd/root/filename.h @@ -1,5 +1,5 @@ -/* Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved +/* Copyright (C) 1999-2024 by The D Language Foundation, All Rights Reserved * written by Walter Bright * https://www.digitalmars.com * Distributed under the Boost Software License, Version 1.0. diff --git a/dmd/root/hash.d b/dmd/root/hash.d index 2acee35c4f3..441620e60b4 100644 --- a/dmd/root/hash.d +++ b/dmd/root/hash.d @@ -1,7 +1,7 @@ /** * Hash functions for arbitrary binary data. * - * Copyright: Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved + * Copyright: Copyright (C) 1999-2024 by The D Language Foundation, All Rights Reserved * Authors: Martin Nowak, Walter Bright, https://www.digitalmars.com * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/root/hash.d, root/_hash.d) diff --git a/dmd/root/longdouble.d b/dmd/root/longdouble.d index f26a1a8d989..bf203bbcacf 100644 --- a/dmd/root/longdouble.d +++ b/dmd/root/longdouble.d @@ -1,7 +1,7 @@ /** * 80-bit floating point value implementation if the C/D compiler does not support them natively. * - * Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved + * Copyright (C) 1999-2024 by The D Language Foundation, All Rights Reserved * All Rights Reserved, written by Rainer Schuetze * https://www.digitalmars.com * Distributed under the Boost Software License, Version 1.0. diff --git a/dmd/root/longdouble.h b/dmd/root/longdouble.h index a0dfaea9143..328aae2f58d 100644 --- a/dmd/root/longdouble.h +++ b/dmd/root/longdouble.h @@ -1,5 +1,5 @@ -/* Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved +/* Copyright (C) 1999-2024 by The D Language Foundation, All Rights Reserved * written by Rainer Schuetze * https://www.digitalmars.com * Distributed under the Boost Software License, Version 1.0. diff --git a/dmd/root/man.d b/dmd/root/man.d index 916542886af..8a84edf8f47 100644 --- a/dmd/root/man.d +++ b/dmd/root/man.d @@ -1,7 +1,7 @@ /** * Open an online manual page. * - * Copyright: Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved + * Copyright: Copyright (C) 1999-2024 by The D Language Foundation, All Rights Reserved * Authors: Walter Bright, https://www.digitalmars.com * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/root/man.d, root/_man.d) diff --git a/dmd/root/object.h b/dmd/root/object.h index 8e505f036c7..f56cb176017 100644 --- a/dmd/root/object.h +++ b/dmd/root/object.h @@ -1,5 +1,5 @@ -/* Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved +/* Copyright (C) 1999-2024 by The D Language Foundation, All Rights Reserved * written by Walter Bright * https://www.digitalmars.com * Distributed under the Boost Software License, Version 1.0. diff --git a/dmd/root/optional.d b/dmd/root/optional.d index bc1016b102a..e7d0e1ef785 100644 --- a/dmd/root/optional.d +++ b/dmd/root/optional.d @@ -1,7 +1,7 @@ /** * Implementation of an 'Optional' type * - * Copyright: Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved + * Copyright: Copyright (C) 1999-2024 by The D Language Foundation, All Rights Reserved * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright) * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/root/optional.d, root/_optional.d) diff --git a/dmd/root/optional.h b/dmd/root/optional.h index 353332c2199..a92deddc638 100644 --- a/dmd/root/optional.h +++ b/dmd/root/optional.h @@ -3,7 +3,7 @@ /** * Optional implementation. * - * Copyright: Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved + * Copyright: Copyright (C) 1999-2024 by The D Language Foundation, All Rights Reserved * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright) * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/root/optional.h, root/_optional.h) diff --git a/dmd/root/port.d b/dmd/root/port.d index 01be55febb1..806fc1d5b20 100644 --- a/dmd/root/port.d +++ b/dmd/root/port.d @@ -1,7 +1,7 @@ /** * Portable routines for functions that have different implementations on different platforms. * - * Copyright: Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved + * Copyright: Copyright (C) 1999-2024 by The D Language Foundation, All Rights Reserved * Authors: Walter Bright, https://www.digitalmars.com * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/root/port.d, root/_port.d) diff --git a/dmd/root/port.h b/dmd/root/port.h index 6fa3c000e5a..6c7dddd43ae 100644 --- a/dmd/root/port.h +++ b/dmd/root/port.h @@ -1,5 +1,5 @@ -/* Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved +/* Copyright (C) 1999-2024 by The D Language Foundation, All Rights Reserved * written by Walter Bright * https://www.digitalmars.com * Distributed under the Boost Software License, Version 1.0. diff --git a/dmd/root/region.d b/dmd/root/region.d index 9fc57f1e3a8..a9fab162537 100644 --- a/dmd/root/region.d +++ b/dmd/root/region.d @@ -1,7 +1,7 @@ /** * Region storage allocator implementation. * - * Copyright: Copyright (C) 2019-2023 by The D Language Foundation, All Rights Reserved + * Copyright: Copyright (C) 2019-2024 by The D Language Foundation, All Rights Reserved * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright) * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/root/region.d, root/_region.d) diff --git a/dmd/root/rmem.d b/dmd/root/rmem.d index cff5c4cf7ec..19652072376 100644 --- a/dmd/root/rmem.d +++ b/dmd/root/rmem.d @@ -1,7 +1,7 @@ /** * Allocate memory using `malloc` or the GC depending on the configuration. * - * Copyright: Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved + * Copyright: Copyright (C) 1999-2024 by The D Language Foundation, All Rights Reserved * Authors: Walter Bright, https://www.digitalmars.com * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/root/rmem.d, root/_rmem.d) diff --git a/dmd/root/rmem.h b/dmd/root/rmem.h index 36aa2646fdc..09c0fc07ccc 100644 --- a/dmd/root/rmem.h +++ b/dmd/root/rmem.h @@ -1,5 +1,5 @@ -/* Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved +/* Copyright (C) 1999-2024 by The D Language Foundation, All Rights Reserved * written by Walter Bright * https://www.digitalmars.com * Distributed under the Boost Software License, Version 1.0. diff --git a/dmd/root/speller.d b/dmd/root/speller.d index 7ad08b7216e..ae09cba37fc 100644 --- a/dmd/root/speller.d +++ b/dmd/root/speller.d @@ -3,7 +3,7 @@ * * Does not have any dependencies on the rest of DMD. * - * Copyright: Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved + * Copyright: Copyright (C) 1999-2024 by The D Language Foundation, All Rights Reserved * Authors: Walter Bright, https://www.digitalmars.com * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/root/speller.d, root/_speller.d) diff --git a/dmd/root/string.d b/dmd/root/string.d index 5ee81a9b63d..e82b0d2fe6d 100644 --- a/dmd/root/string.d +++ b/dmd/root/string.d @@ -1,7 +1,7 @@ /** * Contains various string related functions. * - * Copyright: Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved + * Copyright: Copyright (C) 1999-2024 by The D Language Foundation, All Rights Reserved * Authors: Walter Bright, https://www.digitalmars.com * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/root/string.d, root/_string.d) diff --git a/dmd/root/stringtable.d b/dmd/root/stringtable.d index de293eb9b55..1fba919dec5 100644 --- a/dmd/root/stringtable.d +++ b/dmd/root/stringtable.d @@ -1,7 +1,7 @@ /** * A specialized associative array with string keys stored in a variable length structure. * - * Copyright: Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved + * Copyright: Copyright (C) 1999-2024 by The D Language Foundation, All Rights Reserved * Authors: Walter Bright, https://www.digitalmars.com * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/root/stringtable.d, root/_stringtable.d) diff --git a/dmd/root/utf.d b/dmd/root/utf.d index d7ba17f8a0b..7d732f2fbe8 100644 --- a/dmd/root/utf.d +++ b/dmd/root/utf.d @@ -1,7 +1,7 @@ /** * Functions related to UTF encoding. * - * Copyright: Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved + * Copyright: Copyright (C) 1999-2024 by The D Language Foundation, All Rights Reserved * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright) * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/root/utf.d, _utf.d) diff --git a/dmd/rootobject.d b/dmd/rootobject.d index 7867ad5de31..7c926fea055 100644 --- a/dmd/rootobject.d +++ b/dmd/rootobject.d @@ -1,7 +1,7 @@ /** * Provide the root object that AST classes in dmd inherit from. * - * Copyright: Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved + * Copyright: Copyright (C) 1999-2024 by The D Language Foundation, All Rights Reserved * Authors: Walter Bright, https://www.digitalmars.com * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/rootobject.d, _rootobject.d) diff --git a/dmd/safe.d b/dmd/safe.d index bd531c0081e..af81bff0dd1 100644 --- a/dmd/safe.d +++ b/dmd/safe.d @@ -3,7 +3,7 @@ * * Specification: $(LINK2 https://dlang.org/spec/function.html#function-safety, Function Safety) * - * Copyright: Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved + * Copyright: Copyright (C) 1999-2024 by The D Language Foundation, All Rights Reserved * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright) * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/safe.d, _safe.d) diff --git a/dmd/sapply.d b/dmd/sapply.d index 13fe6916531..340fbad78d4 100644 --- a/dmd/sapply.d +++ b/dmd/sapply.d @@ -1,7 +1,7 @@ /** * Provides a depth-first statement visitor. * - * Copyright: Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved + * Copyright: Copyright (C) 1999-2024 by The D Language Foundation, All Rights Reserved * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright) * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/sparse.d, _sparse.d) diff --git a/dmd/scope.h b/dmd/scope.h index cceb5a7e3a8..1535fd07755 100644 --- a/dmd/scope.h +++ b/dmd/scope.h @@ -1,6 +1,6 @@ /* Compiler implementation of the D programming language - * Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved + * Copyright (C) 1999-2024 by The D Language Foundation, All Rights Reserved * written by Walter Bright * https://www.digitalmars.com * Distributed under the Boost Software License, Version 1.0. diff --git a/dmd/semantic2.d b/dmd/semantic2.d index 292cf62c59c..937e746270a 100644 --- a/dmd/semantic2.d +++ b/dmd/semantic2.d @@ -1,7 +1,7 @@ /** * Performs the semantic2 stage, which deals with initializer expressions. * - * Copyright: Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved + * Copyright: Copyright (C) 1999-2024 by The D Language Foundation, All Rights Reserved * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright) * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/semantic2.d, _semantic2.d) diff --git a/dmd/semantic3.d b/dmd/semantic3.d index 7498eaf4458..520e05f4190 100644 --- a/dmd/semantic3.d +++ b/dmd/semantic3.d @@ -1,7 +1,7 @@ /** * Performs the semantic3 stage, which deals with function bodies. * - * Copyright: Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved + * Copyright: Copyright (C) 1999-2024 by The D Language Foundation, All Rights Reserved * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright) * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/semantic3.d, _semantic3.d) diff --git a/dmd/sideeffect.d b/dmd/sideeffect.d index 80c9a46958f..59398a70cb8 100644 --- a/dmd/sideeffect.d +++ b/dmd/sideeffect.d @@ -1,7 +1,7 @@ /** * Find side-effects of expressions. * - * Copyright: Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved + * Copyright: Copyright (C) 1999-2024 by The D Language Foundation, All Rights Reserved * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright) * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/sideeffect.d, _sideeffect.d) diff --git a/dmd/statement.d b/dmd/statement.d index 430454480e1..a79b78acf24 100644 --- a/dmd/statement.d +++ b/dmd/statement.d @@ -3,7 +3,7 @@ * * Specification: $(LINK2 https://dlang.org/spec/statement.html, Statements) * - * Copyright: Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved + * Copyright: Copyright (C) 1999-2024 by The D Language Foundation, All Rights Reserved * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright) * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/statement.d, _statement.d) diff --git a/dmd/statement.h b/dmd/statement.h index 1e493f0d188..ee03d49eb4a 100644 --- a/dmd/statement.h +++ b/dmd/statement.h @@ -1,6 +1,6 @@ /* Compiler implementation of the D programming language - * Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved + * Copyright (C) 1999-2024 by The D Language Foundation, All Rights Reserved * written by Walter Bright * https://www.digitalmars.com * Distributed under the Boost Software License, Version 1.0. diff --git a/dmd/statement_rewrite_walker.d b/dmd/statement_rewrite_walker.d index dcdd9630002..221c5021c52 100644 --- a/dmd/statement_rewrite_walker.d +++ b/dmd/statement_rewrite_walker.d @@ -1,7 +1,7 @@ /** * Provides a visitor for statements that allows rewriting the currently visited node. * - * Copyright: Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved + * Copyright: Copyright (C) 1999-2024 by The D Language Foundation, All Rights Reserved * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright) * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/statement_rewrite_walker.d, _statement_rewrite_walker.d) diff --git a/dmd/statementsem.d b/dmd/statementsem.d index f3afa42b0b1..229cf17bb6a 100644 --- a/dmd/statementsem.d +++ b/dmd/statementsem.d @@ -3,7 +3,7 @@ * * Specification: $(LINK2 https://dlang.org/spec/statement.html, Statements) * - * Copyright: Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved + * Copyright: Copyright (C) 1999-2024 by The D Language Foundation, All Rights Reserved * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright) * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/statementsem.d, _statementsem.d) diff --git a/dmd/staticassert.d b/dmd/staticassert.d index 7cd042e7832..08780ca0781 100644 --- a/dmd/staticassert.d +++ b/dmd/staticassert.d @@ -3,7 +3,7 @@ * * Specification: $(LINK2 https://dlang.org/spec/version.html#static-assert, Static Assert) * - * Copyright: Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved + * Copyright: Copyright (C) 1999-2024 by The D Language Foundation, All Rights Reserved * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright) * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/staticassert.d, _staticassert.d) diff --git a/dmd/staticassert.h b/dmd/staticassert.h index f03ef61c03e..ed76de07012 100644 --- a/dmd/staticassert.h +++ b/dmd/staticassert.h @@ -1,6 +1,6 @@ /* Compiler implementation of the D programming language - * Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved + * Copyright (C) 1999-2024 by The D Language Foundation, All Rights Reserved * written by Walter Bright * https://www.digitalmars.com * Distributed under the Boost Software License, Version 1.0. diff --git a/dmd/staticcond.d b/dmd/staticcond.d index 1d18de31829..72afe029641 100644 --- a/dmd/staticcond.d +++ b/dmd/staticcond.d @@ -1,7 +1,7 @@ /** * Lazily evaluate static conditions for `static if`, `static assert` and template constraints. * - * Copyright: Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved + * Copyright: Copyright (C) 1999-2024 by The D Language Foundation, All Rights Reserved * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright) * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/staticcond.d, _staticcond.d) diff --git a/dmd/stmtstate.d b/dmd/stmtstate.d index 7b2ea972f0e..e1ed16594a8 100644 --- a/dmd/stmtstate.d +++ b/dmd/stmtstate.d @@ -1,7 +1,7 @@ /** * Used to help transform statement AST into flow graph. * - * Copyright: Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved + * Copyright: Copyright (C) 1999-2024 by The D Language Foundation, All Rights Reserved * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright) * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/stmtstate.d, _stmtstate.d) diff --git a/dmd/target.d b/dmd/target.d index 66faa035a2f..dde4944a4f2 100644 --- a/dmd/target.d +++ b/dmd/target.d @@ -15,7 +15,7 @@ * - $(LINK2 https://github.com/ldc-developers/ldc, LDC repository) * - $(LINK2 https://github.com/D-Programming-GDC/gcc, GDC repository) * - * Copyright: Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved + * Copyright: Copyright (C) 1999-2024 by The D Language Foundation, All Rights Reserved * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright) * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/target.d, _target.d) diff --git a/dmd/target.h b/dmd/target.h index ca0e09c88e0..120950570d4 100644 --- a/dmd/target.h +++ b/dmd/target.h @@ -1,6 +1,6 @@ /* Compiler implementation of the D programming language - * Copyright (C) 2013-2023 by The D Language Foundation, All Rights Reserved + * Copyright (C) 2013-2024 by The D Language Foundation, All Rights Reserved * written by Iain Buclaw * https://www.digitalmars.com * Distributed under the Boost Software License, Version 1.0. diff --git a/dmd/template.h b/dmd/template.h index cc7578454a4..09c4912a521 100644 --- a/dmd/template.h +++ b/dmd/template.h @@ -1,6 +1,6 @@ /* Compiler implementation of the D programming language - * Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved + * Copyright (C) 1999-2024 by The D Language Foundation, All Rights Reserved * written by Walter Bright * https://www.digitalmars.com * Distributed under the Boost Software License, Version 1.0. diff --git a/dmd/templateparamsem.d b/dmd/templateparamsem.d index 7762363c8d6..89749d6b7f3 100644 --- a/dmd/templateparamsem.d +++ b/dmd/templateparamsem.d @@ -1,7 +1,7 @@ /** * Semantic analysis of template parameters. * - * Copyright: Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved + * Copyright: Copyright (C) 1999-2024 by The D Language Foundation, All Rights Reserved * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright) * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/templateparamsem.d, _templateparamsem.d) diff --git a/dmd/tokens.d b/dmd/tokens.d index e04fc307073..589bc2b53cd 100644 --- a/dmd/tokens.d +++ b/dmd/tokens.d @@ -3,7 +3,7 @@ * * Specification: $(LINK2 https://dlang.org/spec/lex.html#tokens, Tokens) * - * Copyright: Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved + * Copyright: Copyright (C) 1999-2024 by The D Language Foundation, All Rights Reserved * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright) * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/tokens.d, _tokens.d) diff --git a/dmd/tokens.h b/dmd/tokens.h index 560942d1e47..f944663e430 100644 --- a/dmd/tokens.h +++ b/dmd/tokens.h @@ -1,6 +1,6 @@ /* Compiler implementation of the D programming language - * Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved + * Copyright (C) 1999-2024 by The D Language Foundation, All Rights Reserved * written by Walter Bright * https://www.digitalmars.com * Distributed under the Boost Software License, Version 1.0. diff --git a/dmd/traits.d b/dmd/traits.d index aebc0b5512b..c67ee816d2c 100644 --- a/dmd/traits.d +++ b/dmd/traits.d @@ -3,7 +3,7 @@ * * Specification: $(LINK2 https://dlang.org/spec/traits.html, Traits) * - * Copyright: Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved + * Copyright: Copyright (C) 1999-2024 by The D Language Foundation, All Rights Reserved * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright) * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/traits.d, _traits.d) diff --git a/dmd/typesem.d b/dmd/typesem.d index 4ff8614b631..c9646ebe4f4 100644 --- a/dmd/typesem.d +++ b/dmd/typesem.d @@ -1,7 +1,7 @@ /** * Semantic analysis for D types. * - * Copyright: Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved + * Copyright: Copyright (C) 1999-2024 by The D Language Foundation, All Rights Reserved * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright) * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/typesem.d, _typesem.d) diff --git a/dmd/typinf.d b/dmd/typinf.d index 5890fa1b61d..30dc33728f8 100644 --- a/dmd/typinf.d +++ b/dmd/typinf.d @@ -1,7 +1,7 @@ /** * Generate `TypeInfo` objects, which are needed for run-time introspection of types. * - * Copyright: Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved + * Copyright: Copyright (C) 1999-2024 by The D Language Foundation, All Rights Reserved * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright) * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/typinf.d, _typinf.d) diff --git a/dmd/typinf.h b/dmd/typinf.h index 2df2abb6a98..02a2c7dfa3e 100644 --- a/dmd/typinf.h +++ b/dmd/typinf.h @@ -1,6 +1,6 @@ /* Compiler implementation of the D programming language - * Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved + * Copyright (C) 1999-2024 by The D Language Foundation, All Rights Reserved * written by Walter Bright * https://www.digitalmars.com * Distributed under the Boost Software License, Version 1.0. diff --git a/dmd/utils.d b/dmd/utils.d index bb389b65903..75ee78cdd2e 100644 --- a/dmd/utils.d +++ b/dmd/utils.d @@ -1,7 +1,7 @@ /** * This module defines some utility functions for DMD. * - * Copyright: Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved + * Copyright: Copyright (C) 1999-2024 by The D Language Foundation, All Rights Reserved * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright) * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/utils.d, _utils.d) diff --git a/dmd/version.h b/dmd/version.h index c268bc9b8cf..dd83fd67dff 100644 --- a/dmd/version.h +++ b/dmd/version.h @@ -1,6 +1,6 @@ /* Compiler implementation of the D programming language - * Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved + * Copyright (C) 1999-2024 by The D Language Foundation, All Rights Reserved * written by Walter Bright * https://www.digitalmars.com * Distributed under the Boost Software License, Version 1.0. diff --git a/dmd/visitor.d b/dmd/visitor.d index 5722e10d256..abfd8caa584 100644 --- a/dmd/visitor.d +++ b/dmd/visitor.d @@ -1,7 +1,7 @@ /** * Provides a visitor class visiting all AST nodes present in the compiler. * - * Copyright: Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved + * Copyright: Copyright (C) 1999-2024 by The D Language Foundation, All Rights Reserved * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright) * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/visitor.d, _visitor.d) diff --git a/dmd/visitor.h b/dmd/visitor.h index 360784a1076..7fa08cb0e8b 100644 --- a/dmd/visitor.h +++ b/dmd/visitor.h @@ -1,6 +1,6 @@ /* Compiler implementation of the D programming language - * Copyright (C) 2013-2023 by The D Language Foundation, All Rights Reserved + * Copyright (C) 2013-2024 by The D Language Foundation, All Rights Reserved * https://www.digitalmars.com * Distributed under the Boost Software License, Version 1.0. * https://www.boost.org/LICENSE_1_0.txt diff --git a/dmd/vsoptions.d b/dmd/vsoptions.d index 82aab48dbc9..fc05c35138b 100644 --- a/dmd/vsoptions.d +++ b/dmd/vsoptions.d @@ -1,7 +1,7 @@ /** * When compiling on Windows with the Microsoft toolchain, try to detect the Visual Studio setup. * - * Copyright: Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved + * Copyright: Copyright (C) 1999-2024 by The D Language Foundation, All Rights Reserved * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright) * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/link.d, _vsoptions.d) diff --git a/dmd/vsoptions.h b/dmd/vsoptions.h index 5c6a7c38257..155a139f9ca 100644 --- a/dmd/vsoptions.h +++ b/dmd/vsoptions.h @@ -1,6 +1,6 @@ /* Compiler implementation of the D programming language - * Copyright (C) 2009-2023 by The D Language Foundation, All Rights Reserved + * Copyright (C) 2009-2024 by The D Language Foundation, All Rights Reserved * written by Walter Bright * https://www.digitalmars.com * Distributed under the Boost Software License, Version 1.0. From cb9925b3de57138855c89fde76d6ca208e4e1b75 Mon Sep 17 00:00:00 2001 From: RazvanN7 Date: Tue, 2 Jan 2024 13:43:49 +0200 Subject: [PATCH 176/215] Fix Issue 24295 - [betterC] ICE with new int[] --- dmd/expressionsem.d | 11 ++++++++++- tests/dmd/fail_compilation/test24295.d | 13 +++++++++++++ 2 files changed, 23 insertions(+), 1 deletion(-) create mode 100644 tests/dmd/fail_compilation/test24295.d diff --git a/dmd/expressionsem.d b/dmd/expressionsem.d index 9ce6f4ded9d..55dd4dd3880 100644 --- a/dmd/expressionsem.d +++ b/dmd/expressionsem.d @@ -5115,7 +5115,16 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor tb = tb.isTypeDArray().next.toBasetype(); } - if (global.params.betterC || !sc.needsCodegen()) + if (!global.params.useGC && sc.needsCodegen()) + { + version(IN_GCC) + error(exp.loc, "expression `%s` allocates with the GC and cannot be used with switch `-fno-rtti`", exp.toChars()); + else + error(exp.loc, "expression `%s` allocates with the GC and cannot be used with switch `-betterC`", exp.toChars()); + return setError(); + } + + if (!sc.needsCodegen()) goto LskipNewArrayLowering; /* Class types may inherit base classes that have errors. diff --git a/tests/dmd/fail_compilation/test24295.d b/tests/dmd/fail_compilation/test24295.d new file mode 100644 index 00000000000..58b6e92df8f --- /dev/null +++ b/tests/dmd/fail_compilation/test24295.d @@ -0,0 +1,13 @@ +// REQUIRED_ARGS: -betterC + +/* +TEST_OUTPUT: +--- +fail_compilation/test24295.d(12): Error: expression `new int[](1$?:32=u|64=LU$)` allocates with the GC and cannot be used with switch `-betterC` +--- +*/ + +void f() +{ + int[] overlaps = new int[1]; +} From 9547d1ea0f75064290ccfa45c2e97d0a9c58713a Mon Sep 17 00:00:00 2001 From: Rainer Schuetze Date: Thu, 4 Jan 2024 12:17:07 +0100 Subject: [PATCH 177/215] fix issue 24309 - Memory allocation failed on Azure pipeline only run GC test that requires 4 GB of memory if that's available as *free* physical memory --- .../core/internal/gc/impl/conservative/gc.d | 4 ++-- runtime/druntime/src/core/internal/gc/os.d | 19 +++++++++++++------ 2 files changed, 15 insertions(+), 8 deletions(-) diff --git a/runtime/druntime/src/core/internal/gc/impl/conservative/gc.d b/runtime/druntime/src/core/internal/gc/impl/conservative/gc.d index 6f194126e7e..a5114b77a6a 100644 --- a/runtime/druntime/src/core/internal/gc/impl/conservative/gc.d +++ b/runtime/druntime/src/core/internal/gc/impl/conservative/gc.d @@ -4989,8 +4989,8 @@ version (D_LP64) unittest // only run if the system has enough physical memory size_t sz = 2L^^32; //import core.stdc.stdio; - //printf("availphys = %lld", os_physical_mem()); - if (os_physical_mem() > sz) + //printf("availphys = %lld", os_physical_mem(true)); + if (os_physical_mem(true) > sz) { import core.memory; GC.collect(); diff --git a/runtime/druntime/src/core/internal/gc/os.d b/runtime/druntime/src/core/internal/gc/os.d index 38b60cbbcc4..0db1753575b 100644 --- a/runtime/druntime/src/core/internal/gc/os.d +++ b/runtime/druntime/src/core/internal/gc/os.d @@ -254,23 +254,26 @@ bool isLowOnMem(size_t mapped) nothrow @nogc /** Get the size of available physical memory + Params: + avail = if supported on the current platform, return the currently unused memory + rather than the installed physical memory Returns: size of installed physical RAM */ version (Windows) { - ulong os_physical_mem() nothrow @nogc + ulong os_physical_mem(bool avail) nothrow @nogc { import core.sys.windows.winbase : GlobalMemoryStatus, MEMORYSTATUS; MEMORYSTATUS stat; GlobalMemoryStatus(&stat); - return stat.dwTotalPhys; // limited to 4GB for Win32 + return avail ? stat.dwAvailPhys : stat.dwTotalPhys; // limited to 4GB for Win32 } } else version (Darwin) { extern (C) int sysctl(const int* name, uint namelen, void* oldp, size_t* oldlenp, const void* newp, size_t newlen) @nogc nothrow; - ulong os_physical_mem() nothrow @nogc + ulong os_physical_mem(bool avail) nothrow @nogc { enum { @@ -287,11 +290,15 @@ else version (Darwin) } else version (Posix) { - ulong os_physical_mem() nothrow @nogc + ulong os_physical_mem(bool avail) nothrow @nogc { - import core.sys.posix.unistd : sysconf, _SC_PAGESIZE, _SC_PHYS_PAGES; + import core.sys.posix.unistd; const pageSize = sysconf(_SC_PAGESIZE); - const pages = sysconf(_SC_PHYS_PAGES); + static if (__traits(compiles, _SC_AVPHYS_PAGES)) // not available on all platforms + const sc = avail ? _SC_AVPHYS_PAGES : _SC_PHYS_PAGES; + else + const sc = _SC_PHYS_PAGES; + const pages = sysconf(sc); return pageSize * pages; } } From c58f8a8ac4dac5b07175192ae772ccc8739b6f44 Mon Sep 17 00:00:00 2001 From: Dennis Date: Fri, 5 Jan 2024 14:47:05 +0100 Subject: [PATCH 178/215] Fix 24311 - Named enum with AA base type causes ICE (dlang/dmd!16002) --- dmd/dsymbolsem.d | 4 ++++ dmd/semantic2.d | 23 ++++++++++++++++------- tests/dmd/runnable/staticaa.d | 12 ++++++++++++ 3 files changed, 32 insertions(+), 7 deletions(-) diff --git a/dmd/dsymbolsem.d b/dmd/dsymbolsem.d index 23f0bc5b428..61190109eb6 100644 --- a/dmd/dsymbolsem.d +++ b/dmd/dsymbolsem.d @@ -2698,6 +2698,10 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor em.origValue = e; } em.value = e; + // https://issues.dlang.org/show_bug.cgi?id=24311 + // First enum member is .init value, which gets put into static segment + if (first) + lowerStaticAAs(e, sc); } else if (first) { diff --git a/dmd/semantic2.d b/dmd/semantic2.d index 937e746270a..b4f91ac7cf0 100644 --- a/dmd/semantic2.d +++ b/dmd/semantic2.d @@ -829,7 +829,8 @@ private void doGNUABITagSemantic(ref Expression e, ref Expression* lastTag) } /** - * Try lower a variable's static Associative Array to a newaa struct. + * Try lower a variable's Associative Array initializer to a newaa struct + * so it can be put in static data. * Params: * vd = Variable to lower * sc = Scope @@ -839,11 +840,20 @@ void lowerStaticAAs(VarDeclaration vd, Scope* sc) if (vd.storage_class & STC.manifest) return; if (auto ei = vd._init.isExpInitializer()) - { - scope v = new StaticAAVisitor(sc); - v.vd = vd; - ei.exp.accept(v); - } + lowerStaticAAs(ei.exp, sc); +} + +/** + * Try lower all Associative Array literals in an expression to a newaa struct + * so it can be put in static data. + * Params: + * e = Expression to traverse + * sc = Scope + */ +void lowerStaticAAs(Expression e, Scope* sc) +{ + scope v = new StaticAAVisitor(sc); + e.accept(v); } /// Visit Associative Array literals and lower them to structs for static initialization @@ -851,7 +861,6 @@ private extern(C++) final class StaticAAVisitor : SemanticTimeTransitiveVisitor { alias visit = SemanticTimeTransitiveVisitor.visit; Scope* sc; - VarDeclaration vd; this(Scope* sc) scope @safe { diff --git a/tests/dmd/runnable/staticaa.d b/tests/dmd/runnable/staticaa.d index 606b70e908a..e5b25d1f66a 100644 --- a/tests/dmd/runnable/staticaa.d +++ b/tests/dmd/runnable/staticaa.d @@ -154,6 +154,17 @@ void testLocalStatic() @trusted ///////////////////////////////////////////// +// https://issues.dlang.org/show_bug.cgi?id=24311 +enum E : int[int] { x = [123: 456] } + +void testEnumInit() +{ + E e = E.init; + assert(e[123] == 456); +} + +///////////////////////////////////////////// + void main() { testSimple(); @@ -163,4 +174,5 @@ void main() testClassInit(); testImmutable(); testLocalStatic(); + testEnumInit(); } From 15b3f0239dbdcb178ada4d5ea339ff6f577af398 Mon Sep 17 00:00:00 2001 From: Dennis Korpel Date: Wed, 10 Jan 2024 14:05:45 +0100 Subject: [PATCH 179/215] Fix 24326 - ImportC: segfault on nameless enum translation with -H --- dmd/hdrgen.d | 2 +- tests/dmd/compilable/ctod.i | 7 +++++++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/dmd/hdrgen.d b/dmd/hdrgen.d index 570c662624c..6475c38fcad 100644 --- a/dmd/hdrgen.d +++ b/dmd/hdrgen.d @@ -1551,7 +1551,7 @@ void toCBuffer(Dsymbol s, ref OutBuffer buf, ref HdrGenState hgs) buf.writeByte('}'); buf.writenl(); - if (!hgs.importcHdr) + if (!hgs.importcHdr || !d.ident) return; /* C enums get their members inserted into the symbol table of the enum declaration. diff --git a/tests/dmd/compilable/ctod.i b/tests/dmd/compilable/ctod.i index 94116aba475..b836dcaf8db 100644 --- a/tests/dmd/compilable/ctod.i +++ b/tests/dmd/compilable/ctod.i @@ -27,6 +27,10 @@ extern (C) int x = void; } alias T = S; + enum + { + A, + } /+enum int __DATE__ = 1+/; /+enum int __TIME__ = 1+/; /+enum int __TIMESTAMP__ = 1+/; @@ -69,3 +73,6 @@ typedef S T; #define __TIMESTAMP__ 1 #define __EOF__ 1 #define __VENDOR__ 1 + +// https://issues.dlang.org/show_bug.cgi?id=24326 +enum { A }; From a485514522299b177b58218eb3162e6098c49160 Mon Sep 17 00:00:00 2001 From: Timon Gehr Date: Fri, 12 Jan 2024 21:09:57 +0100 Subject: [PATCH 180/215] fix Issue 24338 - Cannot concatenate dynamic arrays of enum type with static array base type --- runtime/druntime/src/core/internal/traits.d | 4 +++- tests/dmd/compilable/test24338.d | 10 ++++++++++ 2 files changed, 13 insertions(+), 1 deletion(-) create mode 100644 tests/dmd/compilable/test24338.d diff --git a/runtime/druntime/src/core/internal/traits.d b/runtime/druntime/src/core/internal/traits.d index 966839f176a..0b2eb1f21a7 100644 --- a/runtime/druntime/src/core/internal/traits.d +++ b/runtime/druntime/src/core/internal/traits.d @@ -38,7 +38,7 @@ template Unqual(T : const U, U) template BaseElemOf(T) { - static if (is(T == E[N], E, size_t N)) + static if (is(OriginalType!T == E[N], E, size_t N)) alias BaseElemOf = BaseElemOf!E; else alias BaseElemOf = T; @@ -51,6 +51,8 @@ unittest static assert(is(BaseElemOf!(int[1][2]) == int)); static assert(is(BaseElemOf!(int[1][]) == int[1][])); static assert(is(BaseElemOf!(int[][1]) == int[])); + static enum E : int[2]{ test = [0, 1] } + static assert(is(BaseElemOf!(E) == int)); } // [For internal use] diff --git a/tests/dmd/compilable/test24338.d b/tests/dmd/compilable/test24338.d new file mode 100644 index 00000000000..467b8bd71cb --- /dev/null +++ b/tests/dmd/compilable/test24338.d @@ -0,0 +1,10 @@ +// https://issues.dlang.org/show_bug.cgi?id=24338 + +enum Foo: char[4] +{ + elem = "test" +} + +immutable a = [Foo.elem]; +immutable b = [Foo.elem]; +immutable c = a ~ b; From 8c685903cc962934c38202ed43a6d08394351738 Mon Sep 17 00:00:00 2001 From: Martin Kinkelin Date: Wed, 10 Jan 2024 04:53:48 +0100 Subject: [PATCH 181/215] Fix C++ header regressions --- dmd/dsymbol.h | 2 +- dmd/expression.h | 3 +-- dmd/optimize.d | 2 +- dmd/scope.h | 2 +- gen/asm-x86.h | 7 ++++--- gen/pragma.cpp | 6 +++--- gen/toconstelem.cpp | 2 +- 7 files changed, 12 insertions(+), 12 deletions(-) diff --git a/dmd/dsymbol.h b/dmd/dsymbol.h index 9c15ea368b3..025400499d6 100644 --- a/dmd/dsymbol.h +++ b/dmd/dsymbol.h @@ -149,7 +149,7 @@ enum /* Flags for symbol search */ -typedef uint SearchOptFlags; +typedef unsigned SearchOptFlags; enum class SearchOpt : SearchOptFlags { all = 0x00, // default diff --git a/dmd/expression.h b/dmd/expression.h index 93ee693ff66..463f8af6eb4 100644 --- a/dmd/expression.h +++ b/dmd/expression.h @@ -65,6 +65,7 @@ Expression *resolveLoc(Expression *exp, const Loc &loc, Scope *sc); MATCH implicitConvTo(Expression *e, Type *t); Expression *toLvalue(Expression *_this, Scope *sc, const char* action); Expression *modifiableLvalue(Expression* exp, Scope *sc); +Expression *optimize(Expression *exp, int result, bool keepLvalue = false); typedef unsigned char OwnedBy; enum @@ -123,8 +124,6 @@ class Expression : public ASTNode Expression *addressOf(); Expression *deref(); - Expression *optimize(int result, bool keepLvalue = false); - int isConst(); virtual bool isIdentical(const Expression *e) const; virtual Optional toBool(); diff --git a/dmd/optimize.d b/dmd/optimize.d index f86abde5c3e..5eb5429eaae 100644 --- a/dmd/optimize.d +++ b/dmd/optimize.d @@ -272,7 +272,7 @@ package void setLengthVarIfKnown(VarDeclaration lengthVar, Type type) * Returns: * Constant folded version of `e` */ -Expression optimize(Expression e, int result, bool keepLvalue = false) +extern (C++) Expression optimize(Expression e, int result, bool keepLvalue = false) { //printf("optimize() e: %s result: %d keepLvalue %d\n", e.toChars(), result, keepLvalue); Expression ret = e; diff --git a/dmd/scope.h b/dmd/scope.h index b79665ec8b4..936896b970b 100644 --- a/dmd/scope.h +++ b/dmd/scope.h @@ -133,5 +133,5 @@ struct Scope AliasDeclaration *aliasAsg; // if set, then aliasAsg is being assigned a new value, // do not set wasRead for it - Dsymbol *search(const Loc &loc, Identifier *ident, Dsymbol **pscopesym, SearchOptFlags flags = (SearchOptFlags)SearchOpt::all); + Dsymbol *search(const Loc &loc, Identifier *ident, Dsymbol *&pscopesym, SearchOptFlags flags = (SearchOptFlags)SearchOpt::all); }; diff --git a/gen/asm-x86.h b/gen/asm-x86.h index 16d9e790db1..00a7129436c 100644 --- a/gen/asm-x86.h +++ b/gen/asm-x86.h @@ -3743,7 +3743,7 @@ struct AsmProcessor { // DMD uses labels secondarily to other symbols, so check // if IdentifierExp::semantic won't find anything. Dsymbol *scopesym; - if (!sc->search(stmt->loc, ident, &scopesym)) { + if (!sc->search(stmt->loc, ident, scopesym)) { if (LabelDsymbol *labelsym = sc->func->searchLabel(ident, stmt->loc)) { e = createDsymbolExp(stmt->loc, labelsym); if (opTakesLabel()) { @@ -3755,11 +3755,12 @@ struct AsmProcessor { } e = expressionSemantic(e, sc); - e = e->optimize(WANTvalue); + e = optimize(e, WANTvalue); // Special case for floating point constant declarations. if (e->op == EXP::float64) { - Dsymbol *sym = sc->search(stmt->loc, ident, nullptr); + Dsymbol *scopesym; + Dsymbol *sym = sc->search(stmt->loc, ident, scopesym); if (sym) { VarDeclaration *v = sym->isVarDeclaration(); if (v) { diff --git a/gen/pragma.cpp b/gen/pragma.cpp index b90f96de18d..7afb4bca275 100644 --- a/gen/pragma.cpp +++ b/gen/pragma.cpp @@ -24,7 +24,7 @@ namespace { bool parseStringExp(Expression *e, const char *&res) { - e = e->optimize(WANTvalue); + e = optimize(e, WANTvalue); if (e->op != EXP::string_) { return false; } @@ -37,7 +37,7 @@ bool parseStringExp(Expression *e, const char *&res) { } bool parseIntExp(Expression *e, dinteger_t &res) { - e = e->optimize(WANTvalue); + e = optimize(e, WANTvalue); if (auto i = e->isIntegerExp()) { res = i->getInteger(); return true; @@ -46,7 +46,7 @@ bool parseIntExp(Expression *e, dinteger_t &res) { } bool parseBoolExp(Expression *e, bool &res) { - e = e->optimize(WANTvalue); + e = optimize(e, WANTvalue); if (auto i = e->isIntegerExp()) { if (e->type->equals(Type::tbool)) { res = (i->toInteger() != 0); diff --git a/gen/toconstelem.cpp b/gen/toconstelem.cpp index 6fa299da083..c681804af33 100644 --- a/gen/toconstelem.cpp +++ b/gen/toconstelem.cpp @@ -709,7 +709,7 @@ class ToConstElemVisitor : public Visitor { const auto elementCount = llvm::ElementCount(elemCount, false); #endif result = llvm::ConstantVector::getSplat( - elementCount, toConstElem(e->e1->optimize(WANTvalue), p)); + elementCount, toConstElem(optimize(e->e1, WANTvalue), p)); } } From d4d92eaecd652840d7e5b695c806ad24b0efc266 Mon Sep 17 00:00:00 2001 From: Martin Kinkelin Date: Wed, 10 Jan 2024 04:33:40 +0100 Subject: [PATCH 182/215] Bump LDC version / frontend version / Phobos submodule --- CMakeLists.txt | 6 +++--- runtime/phobos | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 89458186f95..f3c388a9938 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -117,10 +117,10 @@ include(GetLinuxDistribution) # # Version information -set(LDC_VERSION "1.36.0") # May be overridden by git hash tag +set(LDC_VERSION "1.37.0") # May be overridden by git hash tag set(DMDFE_MAJOR_VERSION 2) -set(DMDFE_MINOR_VERSION 106) -set(DMDFE_PATCH_VERSION 1) +set(DMDFE_MINOR_VERSION 107) +set(DMDFE_PATCH_VERSION 0) set(DMD_VERSION ${DMDFE_MAJOR_VERSION}.${DMDFE_MINOR_VERSION}.${DMDFE_PATCH_VERSION}) diff --git a/runtime/phobos b/runtime/phobos index ac5257e700d..622c15577e4 160000 --- a/runtime/phobos +++ b/runtime/phobos @@ -1 +1 @@ -Subproject commit ac5257e700d67a0b74092ddfa4b2a50c8deecc0d +Subproject commit 622c15577e4011754ca7072ec2a3a95f6d3a8136 From 2a0e1ce4921b9acbff2fb018a29045a512239b46 Mon Sep 17 00:00:00 2001 From: Martin Kinkelin Date: Sat, 13 Jan 2024 02:55:23 +0100 Subject: [PATCH 183/215] druntime: Add newly required templates to LDC-specific core.internal.atomic block --- runtime/druntime/src/core/internal/atomic.d | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/runtime/druntime/src/core/internal/atomic.d b/runtime/druntime/src/core/internal/atomic.d index 82d9ea19d60..fb35d642a08 100644 --- a/runtime/druntime/src/core/internal/atomic.d +++ b/runtime/druntime/src/core/internal/atomic.d @@ -18,6 +18,8 @@ version (LDC) pragma(inline, true): + enum IsAtomicLockFree(T) = T.sizeof <= 8 || (T.sizeof <= 16 && has128BitCAS); + inout(T) atomicLoad(MemoryOrder order = MemoryOrder.seq, T)(inout(T)* src) pure nothrow @nogc @trusted { alias A = _AtomicType!T; @@ -88,6 +90,11 @@ version (LDC) llvm_memory_fence(_ordering!(order)); } + void atomicSignalFence(MemoryOrder order = MemoryOrder.seq)() pure nothrow @nogc @trusted + { + llvm_memory_fence(_ordering!(order), SynchronizationScope.SingleThread); + } + void pause() pure nothrow @nogc @trusted { version (X86) From c9e8e8069ae113251972eaa2ee461a28194e25f6 Mon Sep 17 00:00:00 2001 From: Martin Kinkelin Date: Sat, 13 Jan 2024 03:30:12 +0100 Subject: [PATCH 184/215] Fix C++ header regressions in 2.107 --- dmd/dsymbol.h | 2 +- dmd/expression.h | 3 +-- dmd/frontend.h | 2 ++ dmd/optimize.d | 2 +- dmd/scope.h | 2 +- 5 files changed, 6 insertions(+), 5 deletions(-) diff --git a/dmd/dsymbol.h b/dmd/dsymbol.h index 7d715b47b31..e463d3d9005 100644 --- a/dmd/dsymbol.h +++ b/dmd/dsymbol.h @@ -147,7 +147,7 @@ enum /* Flags for symbol search */ -typedef uint SearchOptFlags; +typedef unsigned SearchOptFlags; enum class SearchOpt : SearchOptFlags { all = 0x00, // default diff --git a/dmd/expression.h b/dmd/expression.h index f57f6a40295..731f5580493 100644 --- a/dmd/expression.h +++ b/dmd/expression.h @@ -54,6 +54,7 @@ Expression *resolveLoc(Expression *exp, const Loc &loc, Scope *sc); MATCH implicitConvTo(Expression *e, Type *t); Expression *toLvalue(Expression *_this, Scope *sc, const char* action); Expression *modifiableLvalue(Expression* exp, Scope *sc); +Expression *optimize(Expression *exp, int result, bool keepLvalue = false); typedef unsigned char OwnedBy; enum @@ -107,8 +108,6 @@ class Expression : public ASTNode Expression *addressOf(); Expression *deref(); - Expression *optimize(int result, bool keepLvalue = false); - int isConst(); virtual bool isIdentical(const Expression *e) const; virtual Optional toBool(); diff --git a/dmd/frontend.h b/dmd/frontend.h index 7392c7ee940..0534b64385d 100644 --- a/dmd/frontend.h +++ b/dmd/frontend.h @@ -7607,6 +7607,8 @@ class Objc virtual void checkTupleof(Expression* expression, TypeClass* type) const = 0; }; +extern Expression* optimize(Expression* e, int32_t result, bool keepLvalue = false); + template class PermissiveVisitor : public ParseTimeVisitor { diff --git a/dmd/optimize.d b/dmd/optimize.d index f86abde5c3e..5eb5429eaae 100644 --- a/dmd/optimize.d +++ b/dmd/optimize.d @@ -272,7 +272,7 @@ package void setLengthVarIfKnown(VarDeclaration lengthVar, Type type) * Returns: * Constant folded version of `e` */ -Expression optimize(Expression e, int result, bool keepLvalue = false) +extern (C++) Expression optimize(Expression e, int result, bool keepLvalue = false) { //printf("optimize() e: %s result: %d keepLvalue %d\n", e.toChars(), result, keepLvalue); Expression ret = e; diff --git a/dmd/scope.h b/dmd/scope.h index 1535fd07755..7dd6789c024 100644 --- a/dmd/scope.h +++ b/dmd/scope.h @@ -130,5 +130,5 @@ struct Scope AliasDeclaration *aliasAsg; // if set, then aliasAsg is being assigned a new value, // do not set wasRead for it - Dsymbol *search(const Loc &loc, Identifier *ident, Dsymbol **pscopesym, SearchOptFlags flags = (SearchOptFlags)SearchOpt::all); + Dsymbol *search(const Loc &loc, Identifier *ident, Dsymbol *&pscopesym, SearchOptFlags flags = (SearchOptFlags)SearchOpt::all); }; From 18fea55501c08287fde3b2bbec4017eecbc885d5 Mon Sep 17 00:00:00 2001 From: Martin Kinkelin Date: Sun, 14 Jan 2024 02:57:51 +0100 Subject: [PATCH 185/215] druntime: Revise LDC-specific diff wrt. test Makefiles --- runtime/DRuntimeIntegrationTests.cmake | 11 ++--- runtime/druntime/test/common.mak | 40 ++++++++++----- runtime/druntime/test/coverage/Makefile | 6 --- runtime/druntime/test/exceptions/Makefile | 6 +-- .../test/exceptions/long_backtrace_trunc.exp | 2 +- runtime/druntime/test/profile/Makefile | 5 +- runtime/druntime/test/shared/Makefile | 49 ++++++++++++------- 7 files changed, 69 insertions(+), 50 deletions(-) diff --git a/runtime/DRuntimeIntegrationTests.cmake b/runtime/DRuntimeIntegrationTests.cmake index a70a0051131..437f7ba89f2 100644 --- a/runtime/DRuntimeIntegrationTests.cmake +++ b/runtime/DRuntimeIntegrationTests.cmake @@ -34,9 +34,7 @@ else() endif() endif() -if("${TARGET_SYSTEM}" MATCHES "MSVC") - set(cflags_base "CFLAGS_BASE=") -else() +if(NOT "${TARGET_SYSTEM}" MATCHES "MSVC") set(cflags_base "CFLAGS_BASE=-Wall -Wl,-rpath,${CMAKE_BINARY_DIR}/lib${LIB_SUFFIX}") endif() @@ -52,9 +50,10 @@ elseif(${BUILD_SHARED_LIBS} STREQUAL "ON") # gc: replaces druntime modules at link-time and so requires a static druntime list(REMOVE_ITEM testnames cycles gc) endif() -list(REMOVE_ITEM testnames uuid) # MSVC only, custom Makefile (win64.mak) if("${TARGET_SYSTEM}" MATCHES "Windows") list(REMOVE_ITEM testnames valgrind) +else() + list(REMOVE_ITEM testnames uuid) endif() foreach(name ${testnames}) @@ -72,8 +71,8 @@ foreach(name ${testnames}) COMMAND ${CMAKE_COMMAND} -E remove_directory ${outdir} ) add_test(NAME ${fullname} - COMMAND ${GNU_MAKE_BIN} -C ${PROJECT_SOURCE_DIR}/druntime/test/${name} - ROOT=${outdir} DMD=${LDMD_EXE_FULL} MODEL=default BUILD=${build} + COMMAND ${GNU_MAKE_BIN} -C ${PROJECT_SOURCE_DIR}/druntime/test/${name} all + ROOT=${outdir} DMD=${LDMD_EXE_FULL} BUILD=${build} DRUNTIME=${druntime_path_build} DRUNTIMESO=${shared_druntime_path_build} ${cflags_base} ${linkdl} ) diff --git a/runtime/druntime/test/common.mak b/runtime/druntime/test/common.mak index a52c23210f0..8b8275b1aa7 100644 --- a/runtime/druntime/test/common.mak +++ b/runtime/druntime/test/common.mak @@ -1,8 +1,12 @@ # set explicitly in the make cmdline in druntime/Makefile (`test/%/.run` rule): -# LDC: we have no top makefile, include osmodel.mak for OS and set up bash shell -include ../../../../dmd/osmodel.mak -#OS:= -MODEL:= +ifneq (,$(findstring ldmd2,$(DMD))) + # LDC: we have no top makefile, include osmodel.mak for OS and set up bash shell on Windows + MODEL:=default + include ../../../../dmd/osmodel.mak +else + OS:= + MODEL:= +endif BUILD:= DMD:= DRUNTIME:= @@ -12,6 +16,13 @@ QUIET:= TIMELIMIT:= PIC:= +ifeq (,$(findstring ldmd2,$(DMD))) + # Windows: set up bash shell + ifeq (windows,$(OS)) + include ../../../compiler/src/osmodel.mak + endif +endif + LDL:=$(subst -L,,$(LINKDL)) # -ldl SRC:=src GENERATED:=./generated @@ -20,17 +31,22 @@ DRUNTIME_IMPLIB:=$(subst .dll,.lib,$(DRUNTIMESO)) MODEL_FLAG:=$(if $(findstring $(MODEL),default),,-m$(MODEL)) CFLAGS_BASE:=$(if $(findstring $(OS),windows),/Wall,$(MODEL_FLAG) $(PIC) -Wall) -#ifeq (osx64,$(OS)$(MODEL)) -# CFLAGS_BASE+=--target=x86_64-darwin-apple # ARM cpu is not supported by dmd -#endif +ifeq (,$(findstring ldmd2,$(DMD))) + ifeq (osx64,$(OS)$(MODEL)) + CFLAGS_BASE+=--target=x86_64-darwin-apple # ARM cpu is not supported by dmd + endif +endif # LDC: use `-defaultlib=druntime-ldc [-link-defaultlib-shared]` instead of `-defaultlib= -L$(DRUNTIME[_IMPLIB])` -DFLAGS:=$(MODEL_FLAG) $(PIC) -w -I../../src -I../../import -I$(SRC) -defaultlib=druntime-ldc -preview=dip1000 $(if $(findstring $(OS),windows),,-L-lpthread -L-lm $(LINKDL)) +DFLAGS:=$(MODEL_FLAG) $(PIC) -w -I../../src -I../../import -I$(SRC) -defaultlib=$(if $(findstring ldmd2,$(DMD)),druntime-ldc,) -preview=dip1000 $(if $(findstring $(OS),windows),,-L-lpthread -L-lm $(LINKDL)) # LINK_SHARED may be set by importing makefile -# LDC: -link-defaultlib-shared takes care of rpath, linking ldc_rt.dso.o etc. -DFLAGS+=$(if $(LINK_SHARED),-link-defaultlib-shared,) +ifeq (,$(findstring ldmd2,$(DMD))) + DFLAGS+=$(if $(LINK_SHARED),-L$(DRUNTIME_IMPLIB) $(if $(findstring $(OS),windows),-dllimport=defaultLibsOnly),-L$(DRUNTIME)) +else + # LDC: -link-defaultlib-shared takes care of rpath, linking ldc_rt.dso.o etc. + DFLAGS+=$(if $(LINK_SHARED),-link-defaultlib-shared,) +endif ifeq ($(BUILD),debug) - # LDC: link against debug druntime - DFLAGS+=-g -debug -link-defaultlib-debug + DFLAGS+=-g -debug $(if $(findstring ldmd2,$(DMD)),-link-defaultlib-debug,) CFLAGS:=$(CFLAGS_BASE) $(if $(findstring $(OS),windows),/Zi,-g) else DFLAGS+=-O -release diff --git a/runtime/druntime/test/coverage/Makefile b/runtime/druntime/test/coverage/Makefile index 6325399318e..ba5da368a63 100644 --- a/runtime/druntime/test/coverage/Makefile +++ b/runtime/druntime/test/coverage/Makefile @@ -43,18 +43,12 @@ $(ROOT)/merge_override.done: $(ROOT)/%.done: $(ROOT)/%$(DOTEXE) @rm -f $(ROOT)/src-$*.lst $(QUIET)$(SED) $(SED_INPLACE) 's/CHANGEVAR/CHANGE_VAR/g' src/$*.d $(QUIET)$(ROOT)/$* $(ROOT) $(RUN_ARGS) -ifneq (,$(findstring win,$(OS))) - sed -i 's:^src\\:src/:g' $(ROOT)/src-$*.lst -endif $(QUIET)$(SED) $(SED_INPLACE) 's/CHANGE_VAR/CHANGEVAR/g' src/$*.d ifeq (windows,$(OS)) $(QUIET)$(SED) $(SED_INPLACE) 's:^src\\:src/:g' $(ROOT)/src-$*.lst endif $(QUIET)$(DIFF) src-$*.lst_1.exp $(ROOT)/src-$*.lst $(QUIET)$(ROOT)/$* $(ROOT) $(RUN_ARGS) -ifneq (,$(findstring win,$(OS))) - sed -i 's:^src\\:src/:g' $(ROOT)/src-$*.lst -endif $(QUIET)$(SED) $(SED_INPLACE) 's/CHANGEVAR/CHANGE_VAR/g' src/$*.d ifeq (windows,$(OS)) $(QUIET)$(SED) $(SED_INPLACE) 's:^src\\:src/:g' $(ROOT)/src-$*.lst diff --git a/runtime/druntime/test/exceptions/Makefile b/runtime/druntime/test/exceptions/Makefile index f238a528aac..fd975327d9b 100644 --- a/runtime/druntime/test/exceptions/Makefile +++ b/runtime/druntime/test/exceptions/Makefile @@ -42,7 +42,7 @@ $(ROOT)/line_trace.done: $(ROOT)/line_trace$(DOTEXE) @echo Testing line_trace $(QUIET)$(TIMELIMIT)$(ROOT)/line_trace $(RUN_ARGS) > $(ROOT)/line_trace.output # Use sed to canonicalize line_trace.output and compare against expected output in line_trace.exp - $(QUIET)$(SED) "s|^.*/src/|src/|g; s/\[0x[0-9a-f]*\]/\[ADDR\]/g; s/scope //g; s/Nl//g" $(ROOT)/line_trace.output | $(DIFF) line_trace.exp - + $(QUIET)$(SED) "s/\[0x[0-9a-f]*\]/\[ADDR\]/g; s/scope //g; s/Nl//g" $(ROOT)/line_trace.output | $(DIFF) line_trace.exp - @rm -f $(ROOT)/line_trace.output @touch $@ @@ -52,7 +52,7 @@ $(ROOT)/line_trace_21656.done: $(ROOT)/line_trace$(DOTEXE) @mkdir -p $(ROOT)/line_trace_21656 @touch $(ROOT)/line_trace_21656/line_trace $(QUIET)cd $(ROOT)/line_trace_21656 && PATH="..:$$PATH" $(TIMELIMIT)line_trace $(RUN_ARGS) > line_trace.output - $(QUIET)$(SED) "s|^.*/src/|src/|g; s/\[0x[0-9a-f]*\]/\[ADDR\]/g; s/scope //g; s/Nl//g" $(ROOT)/line_trace_21656/line_trace.output | $(DIFF) line_trace.exp - + $(QUIET)$(SED) "s/\[0x[0-9a-f]*\]/\[ADDR\]/g; s/scope //g; s/Nl//g" $(ROOT)/line_trace_21656/line_trace.output | $(DIFF) line_trace.exp - @rm -rf $(ROOT)/line_trace_21656 @touch $@ @@ -60,7 +60,7 @@ $(ROOT)/long_backtrace_trunc.done: $(ROOT)/long_backtrace_trunc$(DOTEXE) @echo Testing long_backtrace_trunc $(QUIET)$(TIMELIMIT)$(ROOT)/long_backtrace_trunc $(RUN_ARGS) > $(ROOT)/long_backtrace_trunc.output # Use sed to canonicalize long_backtrace_trunc.output and compare against expected output in long_backtrace_trunc.exp - $(QUIET)$(SED) "s|^.*/src/|src/|g; s/\[0x[0-9a-f]*\]/\[ADDR\]/g; s/scope //g; s/Nl//g; s|.F.*F.|.|g; s|.G.*G.|.|g" $(ROOT)/long_backtrace_trunc.output | $(DIFF) long_backtrace_trunc.exp - + $(QUIET)$(SED) "s/\[0x[0-9a-f]*\]/\[ADDR\]/g; s/scope //g; s/Nl//g" $(ROOT)/long_backtrace_trunc.output | $(DIFF) long_backtrace_trunc.exp - @rm -f $(ROOT)/long_backtrace_trunc.output @touch $@ diff --git a/runtime/druntime/test/exceptions/long_backtrace_trunc.exp b/runtime/druntime/test/exceptions/long_backtrace_trunc.exp index 2b2d0e54fa6..28f77bacc4d 100644 --- a/runtime/druntime/test/exceptions/long_backtrace_trunc.exp +++ b/runtime/druntime/test/exceptions/long_backtrace_trunc.exp @@ -1,4 +1,4 @@ object.Exception@src/long_backtrace_trunc.d(10): test ---------------- -src/long_backtrace_trunc.d:10 pure @safe int long_backtrace_trunc.AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA!(int).AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA.BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB.CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC.DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD.EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE... +src/long_backtrace_trunc.d:10 pure @safe int long_backtrace_trunc.AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA!(int).AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA.BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB.CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC.DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD.EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE.FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF.GGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGG... src/long_backtrace_trunc.d:31 _Dmain [ADDR] diff --git a/runtime/druntime/test/profile/Makefile b/runtime/druntime/test/profile/Makefile index 86c17b39565..b8e42365dcb 100644 --- a/runtime/druntime/test/profile/Makefile +++ b/runtime/druntime/test/profile/Makefile @@ -1,8 +1,7 @@ include ../common.mak # LDC doesn't support -profile=gc yet -#TESTS:=profile profilegc both -TESTS:=profile +TESTS:=profile $(if $(findstring ldmd2,$(DMD)),,profilegc both) DIFF:=diff --strip-trailing-cr GREP:=grep @@ -24,7 +23,7 @@ endif all: $(addprefix $(ROOT)/,$(addsuffix .done,$(TESTS))) # LDC: enable assertions for BUILD=RELEASE (=> `-O -release`) -$(ROOT)/profile.done: DFLAGS+=-profile -check=assert=on +$(ROOT)/profile.done: DFLAGS+=-profile $(if $(findstring ldmd2,$(DMD)),-check=assert=on,) $(ROOT)/profile.done: $(ROOT)/%.done: $(ROOT)/%$(DOTEXE) @echo Testing $* @rm -f $(ROOT)/mytrace.log $(ROOT)/mytrace.def diff --git a/runtime/druntime/test/shared/Makefile b/runtime/druntime/test/shared/Makefile index 01b5b4f4e86..88a4c3154d1 100644 --- a/runtime/druntime/test/shared/Makefile +++ b/runtime/druntime/test/shared/Makefile @@ -1,5 +1,5 @@ # LDC: druntime DLL supported on Windows -LINK_SHARED:=1 +LINK_SHARED:=$(if $(findstring ldmd2,$(DMD)),1,$(if $(findstring $(OS),windows),$(SHARED),1)) include ../common.mak # affected by LINK_SHARED! @@ -7,8 +7,10 @@ include ../common.mak # affected by LINK_SHARED! ifeq (windows,$(OS)) -# LDC: required for executables to implicitly dllimport DLL data symbols -DFLAGS+=-dllimport=all +ifneq (,$(findstring ldmd2,$(DMD))) + # LDC: required for executables to implicitly dllimport DLL data symbols + DFLAGS+=-dllimport=all +endif TESTS:=loadlibwin dllrefcount dllgc dynamiccast ifeq ($(SHARED),1) @@ -35,7 +37,9 @@ $(ROOT)/loadlibwin$(DOTEXE): $(SRC)/loadlibwin.d $(QUIET)$(DMD) $(DFLAGS) -of$@ $< # LDC: this test is designed for .exe & .dll with separate druntimes +ifneq (,$(findstring ldmd2,$(DMD))) $(ROOT)/dllgc$(DOTEXE): DFLAGS+=-link-defaultlib-shared=false -dllimport=none +endif $(ROOT)/dllgc$(DOTEXE): $(SRC)/dllgc.d $(QUIET)$(DMD) $(DFLAGS) -version=DLL -shared -of$(ROOT)/dllgc$(DOTDLL) $< @@ -46,6 +50,7 @@ $(ROOT)/dynamiccast$(DOTEXE): $(SRC)/dynamiccast.d $(QUIET)$(DMD) $(DFLAGS) -of$@ $< # LDC addition: test teardown with separate druntimes, with the DLL using the .exe GC +ifneq (,$(findstring ldmd2,$(DMD))) dll_gc_proxy_teardown: DFLAGS+=-link-defaultlib-shared=false -dllimport=none dll_gc_proxy_teardown: $(SRC)/dll_gc_proxy_teardown.d $(QUIET)$(DMD) $(DFLAGS) -shared -L/EXPORT:gc_setProxy -L/EXPORT:gc_clrProxy -version=DLL -of$(ROOT)/dll_gc_proxy_teardown$(DOTDLL) $< @@ -54,32 +59,38 @@ dll_gc_proxy_teardown: $(SRC)/dll_gc_proxy_teardown.d $(QUIET)$(DMD) $(DFLAGS) -version=NoUnload -of$(ROOT)/load_dll_gc_proxy_teardown_nounload$(DOTEXE) $< $(QUIET)$(ROOT)/load_dll_gc_proxy_teardown$(DOTEXE) $(QUIET)$(ROOT)/load_dll_gc_proxy_teardown_nounload$(DOTEXE) +endif # LDC: include Posix tests too endif # Windows -TESTS+=link load linkD linkDR loadDR dynamiccast -TESTS+=link_linkdep link_loaddep load_loaddep load_13414 # LDC: disable 3 tests on Mac, 1 on Windows -ifneq ($(OS),osx) - # * `host` loads two modules with the same name, which is currently disallowed - # by the (potentially overly eager) module collision detection on OS X. - # * `finalize` fails starting with macOS 10.13, as .dylibs with TLS can't be - # unloaded anymore (https://github.com/ldc-developers/ldc/issues/3002). - # * FIXME: `load_linkdep` - # it might fail because of unimplemented `getDependencies()` in rt.sections_elf_shared - ifneq (,$(findstring win,$(OS))) - # LDC FIXME: disable `load_linkdep` on Windows - needs `getDependencies()` - TESTS+=host finalize - else - TESTS+=host finalize load_linkdep - endif +ifeq (,$(findstring ldmd2,$(DMD))) + TESTS:=link load linkD linkDR loadDR host finalize dynamiccast + TESTS+=link_linkdep load_linkdep link_loaddep load_loaddep load_13414 +else + TESTS+=link load linkD linkDR loadDR dynamiccast + TESTS+=link_linkdep link_loaddep load_loaddep load_13414 + ifneq ($(OS),osx) + # * `host` loads two modules with the same name, which is currently disallowed + # by the (potentially overly eager) module collision detection on OS X. + # * `finalize` fails starting with macOS 10.13, as .dylibs with TLS can't be + # unloaded anymore (https://github.com/ldc-developers/ldc/issues/3002). + # * FIXME: `load_linkdep` + # it might fail because of unimplemented `getDependencies()` in rt.sections_elf_shared + ifneq (,$(findstring win,$(OS))) + # LDC FIXME: disable `load_linkdep` on Windows - needs `getDependencies()` + TESTS+=host finalize + else + TESTS+=host finalize load_linkdep + endif + endif endif EXPORT_DYNAMIC=$(if $(findstring $(OS),linux freebsd dragonflybsd),-L--export-dynamic,) NO_AS_NEEDED=$(if $(findstring $(OS),linux freebsd dragonflybsd),-L--no-as-needed,) -all: $(addprefix $(ROOT)/,$(addsuffix .done,$(TESTS))) $(if $(findstring $(OS),windows),dll_gc_proxy_teardown,) +all: $(addprefix $(ROOT)/,$(addsuffix .done,$(TESTS))) $(if $(findstring ldmd2,$(DMD)),$(if $(findstring $(OS),windows),dll_gc_proxy_teardown,),) $(ROOT)/loadDR.done $(ROOT)/host.done: RUN_ARGS:=$(DRUNTIMESO) From fcce99c4b36cf35aff8931fc9f84c8e9a1cc80a4 Mon Sep 17 00:00:00 2001 From: Iain Buclaw Date: Tue, 16 Jan 2024 16:46:06 +0100 Subject: [PATCH 186/215] core.stdc.stdatomic: Deduplicate atomic_fetch_op functions Puts the main logic into its own private template. Co-authored-by: richard (rikki) andrew cattermole --- runtime/druntime/src/core/stdc/stdatomic.d | 218 ++++++--------------- 1 file changed, 59 insertions(+), 159 deletions(-) diff --git a/runtime/druntime/src/core/stdc/stdatomic.d b/runtime/druntime/src/core/stdc/stdatomic.d index ae17e040da7..3565f0770bc 100644 --- a/runtime/druntime/src/core/stdc/stdatomic.d +++ b/runtime/druntime/src/core/stdc/stdatomic.d @@ -775,7 +775,7 @@ pragma(inline, true) A atomic_fetch_add_impl(A, M)(shared(A)* obj, M arg) @trusted { assert(obj !is null); - return atomicFetchAdd(cast(A*)obj, arg); + return atomic_fetch_op!(memory_order.memory_order_seq_cst, "+=")(cast(A*)obj, arg); } /// @@ -790,7 +790,7 @@ pragma(inline, true) A atomic_fetch_sub_impl(A, M)(shared(A)* obj, M arg) @trusted { assert(obj !is null); - return atomicFetchSub(cast(A*)obj, arg); + return atomic_fetch_op!(memory_order.memory_order_seq_cst, "-=")(cast(A*)obj, arg); } /// @@ -810,15 +810,15 @@ A atomic_fetch_add_explicit_impl(A, M)(shared(A)* obj, M arg, memory_order order final switch(order) { case memory_order.memory_order_relaxed: - return atomicFetchAdd!(memory_order.memory_order_relaxed)(cast(A*)obj, arg); + return atomic_fetch_op!(memory_order.memory_order_relaxed, "+=")(cast(A*)obj, arg); case memory_order.memory_order_acquire: - return atomicFetchAdd!(memory_order.memory_order_acquire)(cast(A*)obj, arg); + return atomic_fetch_op!(memory_order.memory_order_acquire, "+=")(cast(A*)obj, arg); case memory_order.memory_order_release: - return atomicFetchAdd!(memory_order.memory_order_release)(cast(A*)obj, arg); + return atomic_fetch_op!(memory_order.memory_order_release, "+=")(cast(A*)obj, arg); case memory_order.memory_order_acq_rel: - return atomicFetchAdd!(memory_order.memory_order_acq_rel)(cast(A*)obj, arg); + return atomic_fetch_op!(memory_order.memory_order_acq_rel, "+=")(cast(A*)obj, arg); case memory_order.memory_order_seq_cst: - return atomicFetchAdd!(memory_order.memory_order_seq_cst)(cast(A*)obj, arg); + return atomic_fetch_op!(memory_order.memory_order_seq_cst, "+=")(cast(A*)obj, arg); } } @@ -839,15 +839,15 @@ A atomic_fetch_sub_explicit_impl(A, M)(shared(A)* obj, M arg, memory_order order final switch(order) { case memory_order.memory_order_relaxed: - return atomicFetchSub!(memory_order.memory_order_relaxed)(cast(A*)obj, arg); + return atomic_fetch_op!(memory_order.memory_order_relaxed, "-=")(cast(A*)obj, arg); case memory_order.memory_order_acquire: - return atomicFetchSub!(memory_order.memory_order_acquire)(cast(A*)obj, arg); + return atomic_fetch_op!(memory_order.memory_order_acquire, "-=")(cast(A*)obj, arg); case memory_order.memory_order_release: - return atomicFetchSub!(memory_order.memory_order_release)(cast(A*)obj, arg); + return atomic_fetch_op!(memory_order.memory_order_release, "-=")(cast(A*)obj, arg); case memory_order.memory_order_acq_rel: - return atomicFetchSub!(memory_order.memory_order_acq_rel)(cast(A*)obj, arg); + return atomic_fetch_op!(memory_order.memory_order_acq_rel, "-=")(cast(A*)obj, arg); case memory_order.memory_order_seq_cst: - return atomicFetchSub!(memory_order.memory_order_seq_cst)(cast(A*)obj, arg); + return atomic_fetch_op!(memory_order.memory_order_seq_cst, "-=")(cast(A*)obj, arg); } } @@ -864,17 +864,7 @@ pragma(inline, true) A atomic_fetch_or_impl(A, M)(shared(A)* obj, M arg) @trusted { assert(obj !is null); - - // copied from atomicOp - - A set, get = atomicLoad(cast(A*)obj); - - do - { - set = get | arg; - } while (!atomicCompareExchangeWeak!(memory_order.memory_order_seq_cst, memory_order.memory_order_seq_cst)(cast(A*)obj, &get, cast(A)set)); - - return get; + return atomic_fetch_op!(memory_order.memory_order_seq_cst, "|=")(cast(A*)obj, arg); } /// @@ -891,52 +881,19 @@ A atomic_fetch_or_explicit_impl(A, M)(shared(A)* obj, M arg, memory_order order) { assert(obj !is null); - A set, get; - final switch(order) { case memory_order.memory_order_relaxed: - get = atomicLoad!(memory_order.memory_order_relaxed)(cast(A*)obj); - do - { - set = get | arg; - } while (!atomicCompareExchangeWeak!(memory_order.memory_order_relaxed, memory_order.memory_order_relaxed)(cast(A*)obj, &get, cast(A)set)); - break; - + return atomic_fetch_op!(memory_order.memory_order_relaxed, "|=")(cast(A*)obj, arg); case memory_order.memory_order_acquire: - get = atomicLoad!(memory_order.memory_order_acquire)(cast(A*)obj); - do - { - set = get | arg; - } while (!atomicCompareExchangeWeak!(memory_order.memory_order_acquire, memory_order.memory_order_acquire)(cast(A*)obj, &get, cast(A)set)); - break; - + return atomic_fetch_op!(memory_order.memory_order_acquire, "|=")(cast(A*)obj, arg); case memory_order.memory_order_release: - get = atomicLoad!(memory_order.memory_order_relaxed)(cast(A*)obj); - do - { - set = get | arg; - } while (!atomicCompareExchangeWeak!(memory_order.memory_order_release, memory_order.memory_order_release)(cast(A*)obj, &get, cast(A)set)); - break; - + return atomic_fetch_op!(memory_order.memory_order_release, "|=")(cast(A*)obj, arg); case memory_order.memory_order_acq_rel: - get = atomicLoad!(memory_order.memory_order_acq_rel)(cast(A*)obj); - do - { - set = get | arg; - } while (!atomicCompareExchangeWeak!(memory_order.memory_order_acq_rel, memory_order.memory_order_acq_rel)(cast(A*)obj, &get, cast(A)set)); - break; - + return atomic_fetch_op!(memory_order.memory_order_acq_rel, "|=")(cast(A*)obj, arg); case memory_order.memory_order_seq_cst: - get = atomicLoad!(memory_order.memory_order_relaxed)(cast(A*)obj); - do - { - set = get | arg; - } while (!atomicCompareExchangeWeak!(memory_order.memory_order_seq_cst, memory_order.memory_order_seq_cst)(cast(A*)obj, &get, cast(A)set)); - break; + return atomic_fetch_op!(memory_order.memory_order_seq_cst, "|=")(cast(A*)obj, arg); } - - return get; } /// @@ -952,17 +909,7 @@ pragma(inline, true) A atomic_fetch_xor_impl(A, M)(shared(A)* obj, M arg) @trusted { assert(obj !is null); - - // copied from atomicOp - - A set, get = atomicLoad(cast(A*)obj); - - do - { - set = get ^ arg; - } while (!atomicCompareExchangeWeak!(memory_order.memory_order_seq_cst, memory_order.memory_order_seq_cst)(cast(A*)obj, &get, cast(A)set)); - - return get; + return atomic_fetch_op!(memory_order.memory_order_seq_cst, "^=")(cast(A*)obj, arg); } /// @@ -979,52 +926,19 @@ A atomic_fetch_xor_explicit_impl(A, M)(shared(A)* obj, M arg, memory_order order { assert(obj !is null); - A set, get; - final switch(order) { case memory_order.memory_order_relaxed: - get = atomicLoad!(memory_order.memory_order_relaxed)(cast(A*)obj); - do - { - set = get ^ arg; - } while (!atomicCompareExchangeWeak!(memory_order.memory_order_relaxed, memory_order.memory_order_relaxed)(cast(A*)obj, &get, cast(A)set)); - break; - + return atomic_fetch_op!(memory_order.memory_order_relaxed, "^=")(cast(A*)obj, arg); case memory_order.memory_order_acquire: - get = atomicLoad!(memory_order.memory_order_acquire)(cast(A*)obj); - do - { - set = get ^ arg; - } while (!atomicCompareExchangeWeak!(memory_order.memory_order_acquire, memory_order.memory_order_acquire)(cast(A*)obj, &get, cast(A)set)); - break; - + return atomic_fetch_op!(memory_order.memory_order_acquire, "^=")(cast(A*)obj, arg); case memory_order.memory_order_release: - get = atomicLoad!(memory_order.memory_order_relaxed)(cast(A*)obj); - do - { - set = get ^ arg; - } while (!atomicCompareExchangeWeak!(memory_order.memory_order_release, memory_order.memory_order_release)(cast(A*)obj, &get, cast(A)set)); - break; - + return atomic_fetch_op!(memory_order.memory_order_release, "^=")(cast(A*)obj, arg); case memory_order.memory_order_acq_rel: - get = atomicLoad!(memory_order.memory_order_acq_rel)(cast(A*)obj); - do - { - set = get ^ arg; - } while (!atomicCompareExchangeWeak!(memory_order.memory_order_acq_rel, memory_order.memory_order_acq_rel)(cast(A*)obj, &get, cast(A)set)); - break; - + return atomic_fetch_op!(memory_order.memory_order_acq_rel, "^=")(cast(A*)obj, arg); case memory_order.memory_order_seq_cst: - get = atomicLoad!(memory_order.memory_order_relaxed)(cast(A*)obj); - do - { - set = get ^ arg; - } while (!atomicCompareExchangeWeak!(memory_order.memory_order_seq_cst, memory_order.memory_order_seq_cst)(cast(A*)obj, &get, cast(A)set)); - break; + return atomic_fetch_op!(memory_order.memory_order_seq_cst, "^=")(cast(A*)obj, arg); } - - return get; } /// @@ -1040,17 +954,7 @@ pragma(inline, true) A atomic_fetch_and_impl(A, M)(shared(A)* obj, M arg) @trusted { assert(obj !is null); - - // copied from atomicOp - - A set, get = atomicLoad(cast(A*)obj); - - do - { - set = get & arg; - } while (!atomicCompareExchangeWeak!(memory_order.memory_order_seq_cst, memory_order.memory_order_seq_cst)(cast(A*)obj, &get, cast(A)set)); - - return get; + return atomic_fetch_op!(memory_order.memory_order_seq_cst, "&=")(cast(A*)obj, arg); } /// @@ -1067,52 +971,19 @@ A atomic_fetch_and_explicit_impl(A, M)(shared(A)* obj, M arg, memory_order order { assert(obj !is null); - A set, get; - final switch(order) { case memory_order.memory_order_relaxed: - get = atomicLoad!(memory_order.memory_order_relaxed)(cast(A*)obj); - do - { - set = get & arg; - } while (!atomicCompareExchangeWeak!(memory_order.memory_order_relaxed, memory_order.memory_order_relaxed)(cast(A*)obj, &get, cast(A)set)); - break; - + return atomic_fetch_op!(memory_order.memory_order_relaxed, "&=")(cast(A*)obj, arg); case memory_order.memory_order_acquire: - get = atomicLoad!(memory_order.memory_order_acquire)(cast(A*)obj); - do - { - set = get & arg; - } while (!atomicCompareExchangeWeak!(memory_order.memory_order_acquire, memory_order.memory_order_acquire)(cast(A*)obj, &get, cast(A)set)); - break; - + return atomic_fetch_op!(memory_order.memory_order_acquire, "&=")(cast(A*)obj, arg); case memory_order.memory_order_release: - get = atomicLoad!(memory_order.memory_order_relaxed)(cast(A*)obj); - do - { - set = get & arg; - } while (!atomicCompareExchangeWeak!(memory_order.memory_order_release, memory_order.memory_order_release)(cast(A*)obj, &get, cast(A)set)); - break; - + return atomic_fetch_op!(memory_order.memory_order_release, "&=")(cast(A*)obj, arg); case memory_order.memory_order_acq_rel: - get = atomicLoad!(memory_order.memory_order_acq_rel)(cast(A*)obj); - do - { - set = get & arg; - } while (!atomicCompareExchangeWeak!(memory_order.memory_order_acq_rel, memory_order.memory_order_acq_rel)(cast(A*)obj, &get, cast(A)set)); - break; - + return atomic_fetch_op!(memory_order.memory_order_acq_rel, "&=")(cast(A*)obj, arg); case memory_order.memory_order_seq_cst: - get = atomicLoad!(memory_order.memory_order_relaxed)(cast(A*)obj); - do - { - set = get & arg; - } while (!atomicCompareExchangeWeak!(memory_order.memory_order_seq_cst, memory_order.memory_order_seq_cst)(cast(A*)obj, &get, cast(A)set)); - break; + return atomic_fetch_op!(memory_order.memory_order_seq_cst, "&=")(cast(A*)obj, arg); } - - return get; } /// @@ -1122,3 +993,32 @@ unittest atomic_fetch_and_explicit_impl(&val, 3, memory_order.memory_order_seq_cst); assert(atomic_load_impl(&val) == 1); } + +private: + +pragma(inline, true) +A atomic_fetch_op(memory_order order, string op, A, M)(A* obj, M arg) @trusted +{ + static if (op == "+=" || op == "-=") + { + static if (op == "+=") + { + return atomicFetchAdd!order(obj, arg); + } + else static if (op == "-=") + { + return atomicFetchSub!order(obj, arg); + } + } + else + { + // copied from core.atomic + A set, get = atomicLoad!(MemoryOrder.raw, A)(obj); + do + { + set = get; + mixin("set " ~ op ~ " arg;"); // will error if op (which is not exposed to user) is invalid + } while (!atomicCompareExchangeWeak!(order, order)(obj, &get, set)); + return get; // unlike core.atomic we return the prior value, not the new one. + } +} From 2daa119b2fa433aa83eb2f145ea44a937b933814 Mon Sep 17 00:00:00 2001 From: Iain Buclaw Date: Mon, 15 Jan 2024 18:31:20 +0100 Subject: [PATCH 187/215] core.atomic: Reject invalid memory models in load, store and exchange - Rejects MemoryOrder.acq_rel in atomicLoad and atomicStore. - Rejects MemoryOrder.acq in atomicExchange. These are rejected as an invalid memory models if ever encountered compiling with GDC or LDC, so make it also rejected by druntime atomics --- runtime/druntime/src/core/internal/atomic.d | 64 +++++++++------------ runtime/druntime/src/core/stdc/stdatomic.d | 22 +++---- 2 files changed, 36 insertions(+), 50 deletions(-) diff --git a/runtime/druntime/src/core/internal/atomic.d b/runtime/druntime/src/core/internal/atomic.d index 3fd5d4a595d..749b1bf14ac 100644 --- a/runtime/druntime/src/core/internal/atomic.d +++ b/runtime/druntime/src/core/internal/atomic.d @@ -54,7 +54,8 @@ version (DigitalMars) inout(T) atomicLoad(MemoryOrder order = MemoryOrder.seq, T)(inout(T)* src) pure nothrow @nogc @trusted if (CanCAS!T) { - static assert(order != MemoryOrder.rel, "invalid MemoryOrder for atomicLoad()"); + static assert(order != MemoryOrder.rel && order != MemoryOrder.acq_rel, + "invalid MemoryOrder for atomicLoad()"); static if (T.sizeof == size_t.sizeof * 2) { @@ -171,7 +172,8 @@ version (DigitalMars) void atomicStore(MemoryOrder order = MemoryOrder.seq, T)(T* dest, T value) pure nothrow @nogc @trusted if (CanCAS!T) { - static assert(order != MemoryOrder.acq, "Invalid MemoryOrder for atomicStore()"); + static assert(order != MemoryOrder.acq && order != MemoryOrder.acq_rel, + "Invalid MemoryOrder for atomicStore()"); static if (T.sizeof == size_t.sizeof * 2) { @@ -293,6 +295,8 @@ version (DigitalMars) T atomicExchange(MemoryOrder order = MemoryOrder.seq, bool result = true, T)(T* dest, T value) pure nothrow @nogc @trusted if (CanCAS!T) { + static assert(order != MemoryOrder.acq, "Invalid MemoryOrder for atomicExchange()"); + version (D_InlineAsm_X86) { static assert(T.sizeof <= 4, "64bit atomicExchange not supported on 32bit target." ); @@ -705,40 +709,35 @@ else version (GNU) inout(T) atomicLoad(MemoryOrder order = MemoryOrder.seq, T)(inout(T)* src) pure nothrow @nogc @trusted if (CanCAS!T) { - // MemoryOrder.rel and MemoryOrder.acq_rel are not valid for load. - static assert(order != MemoryOrder.rel, "invalid MemoryOrder for atomicLoad()"); - - static if (order == MemoryOrder.acq_rel) - enum smodel = PreferAcquireRelease ? MemoryOrder.acq : MemoryOrder.seq; - else - enum smodel = order; + static assert(order != MemoryOrder.rel && order != MemoryOrder.acq_rel, + "invalid MemoryOrder for atomicLoad()"); static if (GNU_Have_Atomics || GNU_Have_LibAtomic) { static if (T.sizeof == ubyte.sizeof) { - ubyte value = __atomic_load_1(cast(shared)src, smodel); + ubyte value = __atomic_load_1(cast(shared)src, order); return *cast(typeof(return)*)&value; } else static if (T.sizeof == ushort.sizeof) { - ushort value = __atomic_load_2(cast(shared)src, smodel); + ushort value = __atomic_load_2(cast(shared)src, order); return *cast(typeof(return)*)&value; } else static if (T.sizeof == uint.sizeof) { - uint value = __atomic_load_4(cast(shared)src, smodel); + uint value = __atomic_load_4(cast(shared)src, order); return *cast(typeof(return)*)&value; } else static if (T.sizeof == ulong.sizeof && GNU_Have_64Bit_Atomics) { - ulong value = __atomic_load_8(cast(shared)src, smodel); + ulong value = __atomic_load_8(cast(shared)src, order); return *cast(typeof(return)*)&value; } else static if (GNU_Have_LibAtomic) { T value; - __atomic_load(T.sizeof, cast(shared)src, &value, smodel); + __atomic_load(T.sizeof, cast(shared)src, &value, order); return *cast(typeof(return)*)&value; } else @@ -755,26 +754,21 @@ else version (GNU) void atomicStore(MemoryOrder order = MemoryOrder.seq, T)(T* dest, T value) pure nothrow @nogc @trusted if (CanCAS!T) { - // MemoryOrder.acq and MemoryOrder.acq_rel are not valid for store. - static assert(order != MemoryOrder.acq, "Invalid MemoryOrder for atomicStore()"); - - static if (order == MemoryOrder.acq_rel) - enum smodel = PreferAcquireRelease ? MemoryOrder.rel : MemoryOrder.seq; - else - enum smodel = order; + static assert(order != MemoryOrder.acq && order != MemoryOrder.acq_rel, + "Invalid MemoryOrder for atomicStore()"); static if (GNU_Have_Atomics || GNU_Have_LibAtomic) { static if (T.sizeof == ubyte.sizeof) - __atomic_store_1(cast(shared)dest, *cast(ubyte*)&value, smodel); + __atomic_store_1(cast(shared)dest, *cast(ubyte*)&value, order); else static if (T.sizeof == ushort.sizeof) - __atomic_store_2(cast(shared)dest, *cast(ushort*)&value, smodel); + __atomic_store_2(cast(shared)dest, *cast(ushort*)&value, order); else static if (T.sizeof == uint.sizeof) - __atomic_store_4(cast(shared)dest, *cast(uint*)&value, smodel); + __atomic_store_4(cast(shared)dest, *cast(uint*)&value, order); else static if (T.sizeof == ulong.sizeof && GNU_Have_64Bit_Atomics) - __atomic_store_8(cast(shared)dest, *cast(ulong*)&value, smodel); + __atomic_store_8(cast(shared)dest, *cast(ulong*)&value, order); else static if (GNU_Have_LibAtomic) - __atomic_store(T.sizeof, cast(shared)dest, cast(void*)&value, smodel); + __atomic_store(T.sizeof, cast(shared)dest, cast(void*)&value, order); else static assert(0, "Invalid template type specified."); } @@ -845,38 +839,34 @@ else version (GNU) T atomicExchange(MemoryOrder order = MemoryOrder.seq, bool result = true, T)(T* dest, T value) pure nothrow @nogc @trusted if (is(T : ulong) || is(T == class) || is(T == interface) || is(T U : U*)) { + static assert(order != MemoryOrder.acq, "Invalid MemoryOrder for atomicExchange()"); + static if (GNU_Have_Atomics || GNU_Have_LibAtomic) { - // MemoryOrder.acq is not valid for exchange. - static if (order == MemoryOrder.acq) - enum smodel = PreferAcquireRelease ? MemoryOrder.acq_rel : MemoryOrder.seq; - else - enum smodel = order; - static if (T.sizeof == byte.sizeof) { - ubyte res = __atomic_exchange_1(cast(shared)dest, *cast(ubyte*)&value, smodel); + ubyte res = __atomic_exchange_1(cast(shared)dest, *cast(ubyte*)&value, order); return *cast(typeof(return)*)&res; } else static if (T.sizeof == short.sizeof) { - ushort res = __atomic_exchange_2(cast(shared)dest, *cast(ushort*)&value, smodel); + ushort res = __atomic_exchange_2(cast(shared)dest, *cast(ushort*)&value, order); return *cast(typeof(return)*)&res; } else static if (T.sizeof == int.sizeof) { - uint res = __atomic_exchange_4(cast(shared)dest, *cast(uint*)&value, smodel); + uint res = __atomic_exchange_4(cast(shared)dest, *cast(uint*)&value, order); return *cast(typeof(return)*)&res; } else static if (T.sizeof == long.sizeof && GNU_Have_64Bit_Atomics) { - ulong res = __atomic_exchange_8(cast(shared)dest, *cast(ulong*)&value, smodel); + ulong res = __atomic_exchange_8(cast(shared)dest, *cast(ulong*)&value, order); return *cast(typeof(return)*)&res; } else static if (GNU_Have_LibAtomic) { T res = void; - __atomic_exchange(T.sizeof, cast(shared)dest, cast(void*)&value, &res, smodel); + __atomic_exchange(T.sizeof, cast(shared)dest, cast(void*)&value, &res, order); return res; } else diff --git a/runtime/druntime/src/core/stdc/stdatomic.d b/runtime/druntime/src/core/stdc/stdatomic.d index 3565f0770bc..70d349ee01b 100644 --- a/runtime/druntime/src/core/stdc/stdatomic.d +++ b/runtime/druntime/src/core/stdc/stdatomic.d @@ -169,6 +169,7 @@ void atomic_flag_clear_explicit_impl()(atomic_flag* obj, memory_order order) break; case memory_order.memory_order_acquire: + case memory_order.memory_order_acq_rel: // Ideally this would error at compile time but alas it is not an intrinsic. // Note: this is not a valid memory order for this operation. atomicStore!(memory_order.memory_order_seq_cst)(&obj.b, false); @@ -178,10 +179,6 @@ void atomic_flag_clear_explicit_impl()(atomic_flag* obj, memory_order order) atomicStore!(memory_order.memory_order_release)(&obj.b, false); break; - case memory_order.memory_order_acq_rel: - atomicStore!(memory_order.memory_order_acq_rel)(&obj.b, false); - break; - case memory_order.memory_order_seq_cst: atomicStore(&obj.b, false); break; @@ -216,7 +213,9 @@ bool atomic_flag_test_and_set_explicit_impl()(atomic_flag* obj, memory_order ord return atomicExchange!(memory_order.memory_order_relaxed)(&obj.b, true); case memory_order.memory_order_acquire: - return atomicExchange!(memory_order.memory_order_acquire)(&obj.b, true); + // Ideally this would error at compile time but alas it is not an intrinsic. + // Note: this is not a valid memory order for this operation. + return atomicExchange!(memory_order.memory_order_seq_cst)(&obj.b, true); case memory_order.memory_order_release: return atomicExchange!(memory_order.memory_order_release)(&obj.b, true); @@ -436,6 +435,7 @@ void atomic_store_explicit_impl(A, C)(shared(A)* obj, C desired, memory_order or break; case memory_order.memory_order_acquire: + case memory_order.memory_order_acq_rel: // Ideally this would error at compile time but alas it is not an intrinsic. // Note: this is not a valid memory order for this operation. atomicStore!(memory_order.memory_order_release)(obj, cast(A)desired); @@ -445,10 +445,6 @@ void atomic_store_explicit_impl(A, C)(shared(A)* obj, C desired, memory_order or atomicStore!(memory_order.memory_order_release)(obj, cast(A)desired); break; - case memory_order.memory_order_acq_rel: - atomicStore!(memory_order.memory_order_acq_rel)(obj, cast(A)desired); - break; - case memory_order.memory_order_seq_cst: atomicStore!(memory_order.memory_order_seq_cst)(obj, cast(A)desired); break; @@ -492,13 +488,11 @@ A atomic_load_explicit_impl(A)(const shared(A)* obj, memory_order order) @truste return atomicLoad!(memory_order.memory_order_acquire)(obj); case memory_order.memory_order_release: + case memory_order.memory_order_acq_rel: // Ideally this would error at compile time but alas it is not an intrinsic. // Note: this is not a valid memory order for this operation. return atomicLoad!(memory_order.memory_order_acquire)(obj); - case memory_order.memory_order_acq_rel: - return atomicLoad!(memory_order.memory_order_acq_rel)(obj); - case memory_order.memory_order_seq_cst: return atomicLoad!(memory_order.memory_order_seq_cst)(obj); } @@ -538,7 +532,9 @@ A atomic_exchange_explicit_impl(A, C)(shared(A)* obj, C desired, memory_order or return atomicExchange!(memory_order.memory_order_relaxed)(obj, cast(A)desired); case memory_order.memory_order_acquire: - return atomicExchange!(memory_order.memory_order_acquire)(obj, cast(A)desired); + // Ideally this would error at compile time but alas it is not an intrinsic. + // Note: this is not a valid memory order for this operation. + return atomicExchange!(memory_order.memory_order_seq_cst)(obj, cast(A)desired); case memory_order.memory_order_release: return atomicExchange!(memory_order.memory_order_release)(obj, cast(A)desired); From ac62f2c4f63f3bfc5d88ef0c56955e3c3a42edac Mon Sep 17 00:00:00 2001 From: Iain Buclaw Date: Wed, 17 Jan 2024 13:54:51 +0100 Subject: [PATCH 188/215] core.atomic: Reject invalid failure memory modules in compare exchange - Rejects MemoryOrder.rel and MemoryOrder.acq_rel as the `fail` argument in atomicCompareExchangeStrong and atomicCompareExchangeWeak. - Rejects `fail` argument having a stronger value than the `succ` memory model. These are rejected as invalid memory models if ever encountered compiling with GDC or LDC, so make it also rejected by druntime atomics. --- runtime/druntime/src/core/internal/atomic.d | 55 +++---- runtime/druntime/src/core/stdc/stdatomic.d | 152 ++------------------ 2 files changed, 32 insertions(+), 175 deletions(-) diff --git a/runtime/druntime/src/core/internal/atomic.d b/runtime/druntime/src/core/internal/atomic.d index 749b1bf14ac..cc28e123f17 100644 --- a/runtime/druntime/src/core/internal/atomic.d +++ b/runtime/druntime/src/core/internal/atomic.d @@ -346,6 +346,10 @@ version (DigitalMars) bool atomicCompareExchangeStrong(MemoryOrder succ = MemoryOrder.seq, MemoryOrder fail = MemoryOrder.seq, T)(T* dest, T* compare, T value) pure nothrow @nogc @trusted if (CanCAS!T) { + static assert(fail != MemoryOrder.rel && fail != MemoryOrder.acq_rel, + "Invalid fail MemoryOrder for atomicCompareExchangeStrong()"); + static assert (succ >= fail, "The first MemoryOrder argument for atomicCompareExchangeStrong() cannot be weaker than the second argument"); + version (D_InlineAsm_X86) { static if (T.sizeof <= 4) @@ -489,6 +493,10 @@ version (DigitalMars) bool atomicCompareExchangeStrongNoResult(MemoryOrder succ = MemoryOrder.seq, MemoryOrder fail = MemoryOrder.seq, T)(T* dest, const T compare, T value) pure nothrow @nogc @trusted if (CanCAS!T) { + static assert(fail != MemoryOrder.rel && fail != MemoryOrder.acq_rel, + "Invalid fail MemoryOrder for atomicCompareExchangeStrongNoResult()"); + static assert (succ >= fail, "The first MemoryOrder argument for atomicCompareExchangeStrongNoResult() cannot be weaker than the second argument"); + version (D_InlineAsm_X86) { static if (T.sizeof <= 4) @@ -692,18 +700,6 @@ else version (GNU) import gcc.builtins; import gcc.config; - // Targets where MemoryOrder.acq_rel is sufficiently cheaper than using - // MemoryOrder.seq, used when the MemoryOrder requested is not valid for - // a given atomic operation. - version (IA64) - private enum PreferAcquireRelease = true; - else version (PPC) - private enum PreferAcquireRelease = true; - else version (PPC64) - private enum PreferAcquireRelease = true; - else - private enum PreferAcquireRelease = false; - enum IsAtomicLockFree(T) = __atomic_is_lock_free(T.sizeof, null); inout(T) atomicLoad(MemoryOrder order = MemoryOrder.seq, T)(inout(T)* src) pure nothrow @nogc @trusted @@ -910,46 +906,29 @@ else version (GNU) private bool atomicCompareExchangeImpl(MemoryOrder succ = MemoryOrder.seq, MemoryOrder fail = MemoryOrder.seq, bool weak, T)(T* dest, T* compare, T value) pure nothrow @nogc @trusted if (CanCAS!T) { + static assert(fail != MemoryOrder.rel && fail != MemoryOrder.acq_rel, + "Invalid fail MemoryOrder for atomicCompareExchange()"); + static assert (succ >= fail, "The first MemoryOrder argument for atomicCompareExchange() cannot be weaker than the second argument"); + bool res = void; static if (GNU_Have_Atomics || GNU_Have_LibAtomic) { - static if (fail == MemoryOrder.rel || fail == MemoryOrder.acq_rel) - { - // MemoryOrder.rel and MemoryOrder.acq_rel are not valid failure models. - enum smodel = (succ != MemoryOrder.seq && PreferAcquireRelease) - ? MemoryOrder.acq_rel : MemoryOrder.seq; - enum fmodel = (succ != MemoryOrder.seq && PreferAcquireRelease) - ? MemoryOrder.raw : MemoryOrder.seq; - } - else static if (fail > succ) - { - // Failure memory model cannot be stronger than success. - enum smodel = (fail != MemoryOrder.seq && PreferAcquireRelease) - ? MemoryOrder.acq_rel : MemoryOrder.seq; - enum fmodel = fail; - } - else - { - enum smodel = succ; - enum fmodel = fail; - } - static if (T.sizeof == byte.sizeof) res = __atomic_compare_exchange_1(cast(shared)dest, compare, *cast(ubyte*)&value, - weak, smodel, fmodel); + weak, succ, fail); else static if (T.sizeof == short.sizeof) res = __atomic_compare_exchange_2(cast(shared)dest, compare, *cast(ushort*)&value, - weak, smodel, fmodel); + weak, succ, fail); else static if (T.sizeof == int.sizeof) res = __atomic_compare_exchange_4(cast(shared)dest, compare, *cast(uint*)&value, - weak, smodel, fmodel); + weak, succ, fail); else static if (T.sizeof == long.sizeof && GNU_Have_64Bit_Atomics) res = __atomic_compare_exchange_8(cast(shared)dest, compare, *cast(ulong*)&value, - weak, smodel, fmodel); + weak, succ, fail); else static if (GNU_Have_LibAtomic) res = __atomic_compare_exchange(T.sizeof, cast(shared)dest, compare, cast(void*)&value, - smodel, fmodel); + succ, fail); else static assert(0, "Invalid template type specified."); } diff --git a/runtime/druntime/src/core/stdc/stdatomic.d b/runtime/druntime/src/core/stdc/stdatomic.d index 70d349ee01b..96f99a4a72f 100644 --- a/runtime/druntime/src/core/stdc/stdatomic.d +++ b/runtime/druntime/src/core/stdc/stdatomic.d @@ -586,84 +586,23 @@ unittest /// pragma(inline, true) -bool atomic_compare_exchange_strong_explicit_impl(A, C)(shared(A)* obj, A* expected, C desired, memory_order succ, memory_order fail) @trusted +bool atomic_compare_exchange_strong_explicit_impl(A, C)(shared(A)* obj, A* expected, C desired, memory_order succ, memory_order /*fail*/) @trusted { assert(obj !is null); - // We use these giant switch inside switch statements - // because as of 2023 they are capable of being for the most part inlined by gdc & ldc when using literal arguments for memory_order. + // NOTE: To not have to deal with all invalid cases, the failure model is ignored for now. final switch(succ) { case memory_order.memory_order_relaxed: - final switch(fail) - { - case memory_order.memory_order_relaxed: - return atomicCompareExchangeStrong!(memory_order.memory_order_relaxed, memory_order.memory_order_relaxed)(cast(A*)obj, expected, cast(A)desired); - case memory_order.memory_order_acquire: - return atomicCompareExchangeStrong!(memory_order.memory_order_relaxed, memory_order.memory_order_acquire)(cast(A*)obj, expected, cast(A)desired); - case memory_order.memory_order_release: - return atomicCompareExchangeStrong!(memory_order.memory_order_relaxed, memory_order.memory_order_release)(cast(A*)obj, expected, cast(A)desired); - case memory_order.memory_order_acq_rel: - return atomicCompareExchangeStrong!(memory_order.memory_order_relaxed, memory_order.memory_order_acq_rel)(cast(A*)obj, expected, cast(A)desired); - case memory_order.memory_order_seq_cst: - return atomicCompareExchangeStrong!(memory_order.memory_order_relaxed, memory_order.memory_order_seq_cst)(cast(A*)obj, expected, cast(A)desired); - } + return atomicCompareExchangeStrong!(memory_order.memory_order_relaxed, memory_order.memory_order_relaxed)(cast(A*)obj, expected, cast(A)desired); case memory_order.memory_order_acquire: - final switch(fail) - { - case memory_order.memory_order_relaxed: - return atomicCompareExchangeStrong!(memory_order.memory_order_acquire, memory_order.memory_order_relaxed)(cast(A*)obj, expected, cast(A)desired); - case memory_order.memory_order_acquire: - return atomicCompareExchangeStrong!(memory_order.memory_order_acquire, memory_order.memory_order_acquire)(cast(A*)obj, expected, cast(A)desired); - case memory_order.memory_order_release: - return atomicCompareExchangeStrong!(memory_order.memory_order_acquire, memory_order.memory_order_release)(cast(A*)obj, expected, cast(A)desired); - case memory_order.memory_order_acq_rel: - return atomicCompareExchangeStrong!(memory_order.memory_order_acquire, memory_order.memory_order_acq_rel)(cast(A*)obj, expected, cast(A)desired); - case memory_order.memory_order_seq_cst: - return atomicCompareExchangeStrong!(memory_order.memory_order_acquire, memory_order.memory_order_seq_cst)(cast(A*)obj, expected, cast(A)desired); - } + return atomicCompareExchangeStrong!(memory_order.memory_order_acquire, memory_order.memory_order_relaxed)(cast(A*)obj, expected, cast(A)desired); case memory_order.memory_order_release: - final switch(fail) - { - case memory_order.memory_order_relaxed: - return atomicCompareExchangeStrong!(memory_order.memory_order_release, memory_order.memory_order_relaxed)(cast(A*)obj, expected, cast(A)desired); - case memory_order.memory_order_acquire: - return atomicCompareExchangeStrong!(memory_order.memory_order_release, memory_order.memory_order_acquire)(cast(A*)obj, expected, cast(A)desired); - case memory_order.memory_order_release: - return atomicCompareExchangeStrong!(memory_order.memory_order_release, memory_order.memory_order_release)(cast(A*)obj, expected, cast(A)desired); - case memory_order.memory_order_acq_rel: - return atomicCompareExchangeStrong!(memory_order.memory_order_release, memory_order.memory_order_acq_rel)(cast(A*)obj, expected, cast(A)desired); - case memory_order.memory_order_seq_cst: - return atomicCompareExchangeStrong!(memory_order.memory_order_release, memory_order.memory_order_seq_cst)(cast(A*)obj, expected, cast(A)desired); - } + return atomicCompareExchangeStrong!(memory_order.memory_order_release, memory_order.memory_order_relaxed)(cast(A*)obj, expected, cast(A)desired); case memory_order.memory_order_acq_rel: - final switch(fail) - { - case memory_order.memory_order_relaxed: - return atomicCompareExchangeStrong!(memory_order.memory_order_acq_rel, memory_order.memory_order_relaxed)(cast(A*)obj, expected, cast(A)desired); - case memory_order.memory_order_acquire: - return atomicCompareExchangeStrong!(memory_order.memory_order_acq_rel, memory_order.memory_order_acquire)(cast(A*)obj, expected, cast(A)desired); - case memory_order.memory_order_release: - return atomicCompareExchangeStrong!(memory_order.memory_order_acq_rel, memory_order.memory_order_release)(cast(A*)obj, expected, cast(A)desired); - case memory_order.memory_order_acq_rel: - return atomicCompareExchangeStrong!(memory_order.memory_order_acq_rel, memory_order.memory_order_acq_rel)(cast(A*)obj, expected, cast(A)desired); - case memory_order.memory_order_seq_cst: - return atomicCompareExchangeStrong!(memory_order.memory_order_acq_rel, memory_order.memory_order_seq_cst)(cast(A*)obj, expected, cast(A)desired); - } + return atomicCompareExchangeStrong!(memory_order.memory_order_acq_rel, memory_order.memory_order_relaxed)(cast(A*)obj, expected, cast(A)desired); case memory_order.memory_order_seq_cst: - final switch(fail) - { - case memory_order.memory_order_relaxed: - return atomicCompareExchangeStrong!(memory_order.memory_order_seq_cst, memory_order.memory_order_relaxed)(cast(A*)obj, expected, cast(A)desired); - case memory_order.memory_order_acquire: - return atomicCompareExchangeStrong!(memory_order.memory_order_seq_cst, memory_order.memory_order_acquire)(cast(A*)obj, expected, cast(A)desired); - case memory_order.memory_order_release: - return atomicCompareExchangeStrong!(memory_order.memory_order_seq_cst, memory_order.memory_order_release)(cast(A*)obj, expected, cast(A)desired); - case memory_order.memory_order_acq_rel: - return atomicCompareExchangeStrong!(memory_order.memory_order_seq_cst, memory_order.memory_order_acq_rel)(cast(A*)obj, expected, cast(A)desired); - case memory_order.memory_order_seq_cst: - return atomicCompareExchangeStrong!(memory_order.memory_order_seq_cst, memory_order.memory_order_seq_cst)(cast(A*)obj, expected, cast(A)desired); - } + return atomicCompareExchangeStrong!(memory_order.memory_order_seq_cst, memory_order.memory_order_relaxed)(cast(A*)obj, expected, cast(A)desired); } } @@ -677,84 +616,23 @@ unittest /// pragma(inline, true) -bool atomic_compare_exchange_weak_explicit_impl(A, C)(shared(A)* obj, A* expected, C desired, memory_order succ, memory_order fail) @trusted +bool atomic_compare_exchange_weak_explicit_impl(A, C)(shared(A)* obj, A* expected, C desired, memory_order succ, memory_order /*fail*/) @trusted { assert(obj !is null); - // We use these giant switch inside switch statements - // because as of 2023 they are capable of being for the most part inlined by gdc & ldc when using literal arguments for memory_order. + // NOTE: To not have to deal with all invalid cases, the failure model is ignored for now. final switch(succ) { case memory_order.memory_order_relaxed: - final switch(fail) - { - case memory_order.memory_order_relaxed: - return atomicCompareExchangeWeak!(memory_order.memory_order_relaxed, memory_order.memory_order_relaxed)(cast(A*)obj, expected, cast(A)desired); - case memory_order.memory_order_acquire: - return atomicCompareExchangeWeak!(memory_order.memory_order_relaxed, memory_order.memory_order_relaxed)(cast(A*)obj, expected, cast(A)desired); - case memory_order.memory_order_release: - return atomicCompareExchangeWeak!(memory_order.memory_order_relaxed, memory_order.memory_order_relaxed)(cast(A*)obj, expected, cast(A)desired); - case memory_order.memory_order_acq_rel: - return atomicCompareExchangeWeak!(memory_order.memory_order_relaxed, memory_order.memory_order_relaxed)(cast(A*)obj, expected, cast(A)desired); - case memory_order.memory_order_seq_cst: - return atomicCompareExchangeWeak!(memory_order.memory_order_relaxed, memory_order.memory_order_relaxed)(cast(A*)obj, expected, cast(A)desired); - } + return atomicCompareExchangeWeak!(memory_order.memory_order_relaxed, memory_order.memory_order_relaxed)(cast(A*)obj, expected, cast(A)desired); case memory_order.memory_order_acquire: - final switch(fail) - { - case memory_order.memory_order_relaxed: - return atomicCompareExchangeWeak!(memory_order.memory_order_acquire, memory_order.memory_order_relaxed)(cast(A*)obj, expected, cast(A)desired); - case memory_order.memory_order_acquire: - return atomicCompareExchangeWeak!(memory_order.memory_order_acquire, memory_order.memory_order_acquire)(cast(A*)obj, expected, cast(A)desired); - case memory_order.memory_order_release: - return atomicCompareExchangeWeak!(memory_order.memory_order_acquire, memory_order.memory_order_release)(cast(A*)obj, expected, cast(A)desired); - case memory_order.memory_order_acq_rel: - return atomicCompareExchangeWeak!(memory_order.memory_order_acquire, memory_order.memory_order_acq_rel)(cast(A*)obj, expected, cast(A)desired); - case memory_order.memory_order_seq_cst: - return atomicCompareExchangeWeak!(memory_order.memory_order_acquire, memory_order.memory_order_seq_cst)(cast(A*)obj, expected, cast(A)desired); - } + return atomicCompareExchangeWeak!(memory_order.memory_order_acquire, memory_order.memory_order_relaxed)(cast(A*)obj, expected, cast(A)desired); case memory_order.memory_order_release: - final switch(fail) - { - case memory_order.memory_order_relaxed: - return atomicCompareExchangeWeak!(memory_order.memory_order_release, memory_order.memory_order_relaxed)(cast(A*)obj, expected, cast(A)desired); - case memory_order.memory_order_acquire: - return atomicCompareExchangeWeak!(memory_order.memory_order_release, memory_order.memory_order_acquire)(cast(A*)obj, expected, cast(A)desired); - case memory_order.memory_order_release: - return atomicCompareExchangeWeak!(memory_order.memory_order_release, memory_order.memory_order_release)(cast(A*)obj, expected, cast(A)desired); - case memory_order.memory_order_acq_rel: - return atomicCompareExchangeWeak!(memory_order.memory_order_release, memory_order.memory_order_acq_rel)(cast(A*)obj, expected, cast(A)desired); - case memory_order.memory_order_seq_cst: - return atomicCompareExchangeWeak!(memory_order.memory_order_release, memory_order.memory_order_seq_cst)(cast(A*)obj, expected, cast(A)desired); - } + return atomicCompareExchangeWeak!(memory_order.memory_order_release, memory_order.memory_order_relaxed)(cast(A*)obj, expected, cast(A)desired); case memory_order.memory_order_acq_rel: - final switch(fail) - { - case memory_order.memory_order_relaxed: - return atomicCompareExchangeWeak!(memory_order.memory_order_acq_rel, memory_order.memory_order_relaxed)(cast(A*)obj, expected, cast(A)desired); - case memory_order.memory_order_acquire: - return atomicCompareExchangeWeak!(memory_order.memory_order_acq_rel, memory_order.memory_order_acquire)(cast(A*)obj, expected, cast(A)desired); - case memory_order.memory_order_release: - return atomicCompareExchangeWeak!(memory_order.memory_order_acq_rel, memory_order.memory_order_release)(cast(A*)obj, expected, cast(A)desired); - case memory_order.memory_order_acq_rel: - return atomicCompareExchangeWeak!(memory_order.memory_order_acq_rel, memory_order.memory_order_acq_rel)(cast(A*)obj, expected, cast(A)desired); - case memory_order.memory_order_seq_cst: - return atomicCompareExchangeWeak!(memory_order.memory_order_acq_rel, memory_order.memory_order_seq_cst)(cast(A*)obj, expected, cast(A)desired); - } + return atomicCompareExchangeWeak!(memory_order.memory_order_acq_rel, memory_order.memory_order_relaxed)(cast(A*)obj, expected, cast(A)desired); case memory_order.memory_order_seq_cst: - final switch(fail) - { - case memory_order.memory_order_relaxed: - return atomicCompareExchangeWeak!(memory_order.memory_order_seq_cst, memory_order.memory_order_relaxed)(cast(A*)obj, expected, cast(A)desired); - case memory_order.memory_order_acquire: - return atomicCompareExchangeWeak!(memory_order.memory_order_seq_cst, memory_order.memory_order_acquire)(cast(A*)obj, expected, cast(A)desired); - case memory_order.memory_order_release: - return atomicCompareExchangeWeak!(memory_order.memory_order_seq_cst, memory_order.memory_order_release)(cast(A*)obj, expected, cast(A)desired); - case memory_order.memory_order_acq_rel: - return atomicCompareExchangeWeak!(memory_order.memory_order_seq_cst, memory_order.memory_order_acq_rel)(cast(A*)obj, expected, cast(A)desired); - case memory_order.memory_order_seq_cst: - return atomicCompareExchangeWeak!(memory_order.memory_order_seq_cst, memory_order.memory_order_seq_cst)(cast(A*)obj, expected, cast(A)desired); - } + return atomicCompareExchangeWeak!(memory_order.memory_order_seq_cst, memory_order.memory_order_relaxed)(cast(A*)obj, expected, cast(A)desired); } } @@ -1014,7 +892,7 @@ A atomic_fetch_op(memory_order order, string op, A, M)(A* obj, M arg) @trusted { set = get; mixin("set " ~ op ~ " arg;"); // will error if op (which is not exposed to user) is invalid - } while (!atomicCompareExchangeWeak!(order, order)(obj, &get, set)); + } while (!atomicCompareExchangeWeak!(order, MemoryOrder.raw)(obj, &get, set)); return get; // unlike core.atomic we return the prior value, not the new one. } } From d2939ca3c07444417bc74a3e0466f62e17a4621e Mon Sep 17 00:00:00 2001 From: Martin Kinkelin Date: Sun, 14 Jan 2024 15:22:20 +0100 Subject: [PATCH 189/215] [adapt new assertion in d_do_test.d for LDC] --- tests/dmd/tools/d_do_test.d | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/tests/dmd/tools/d_do_test.d b/tests/dmd/tools/d_do_test.d index ca6c9ab4b47..864300542f2 100755 --- a/tests/dmd/tools/d_do_test.d +++ b/tests/dmd/tools/d_do_test.d @@ -1509,7 +1509,10 @@ unittest assert(!compareOutput(`Bob took 12 berries`, `Bob took $n$ apples`, ed)); assert( compareOutput(`HINT: ` ~ __FILE_FULL_PATH__ ~ ` is important`, `HINT: $p:d_do_test.d$ is important`, ed)); - assert( compareOutput(`HINT: ` ~ __FILE_FULL_PATH__ ~ ` is important`, `HINT: $p:test/tools/d_do_test.d$ is important`, ed)); + version (LDC) + assert( compareOutput(`HINT: ` ~ __FILE_FULL_PATH__ ~ ` is important`, `HINT: $p:tools/d_do_test.d$ is important`, ed)); + else + assert( compareOutput(`HINT: ` ~ __FILE_FULL_PATH__ ~ ` is important`, `HINT: $p:test/tools/d_do_test.d$ is important`, ed)); ed.sep = "/"; assert(!compareOutput(`See /path/to/druntime/import/object.d`, `See $p:druntime/import/object.d$`, ed)); From a8d5f6bd944b0f36c040a1a0f478d9c17a1f2a4d Mon Sep 17 00:00:00 2001 From: Martin Kinkelin Date: Sun, 14 Jan 2024 18:43:40 +0100 Subject: [PATCH 190/215] druntime: Somewhat revamp test/shared/Makefile --- runtime/DRuntimeIntegrationTests.cmake | 4 +- runtime/druntime/test/shared/Makefile | 146 +++++++++--------- .../druntime/test/shared/src/dynamiccast.d | 5 +- runtime/druntime/test/shared/src/host.c | 2 + runtime/druntime/test/shared/src/utils.di | 2 + runtime/druntime/test/shared/src/utils.h | 4 + 6 files changed, 87 insertions(+), 76 deletions(-) diff --git a/runtime/DRuntimeIntegrationTests.cmake b/runtime/DRuntimeIntegrationTests.cmake index 437f7ba89f2..a10b5607593 100644 --- a/runtime/DRuntimeIntegrationTests.cmake +++ b/runtime/DRuntimeIntegrationTests.cmake @@ -71,10 +71,10 @@ foreach(name ${testnames}) COMMAND ${CMAKE_COMMAND} -E remove_directory ${outdir} ) add_test(NAME ${fullname} - COMMAND ${GNU_MAKE_BIN} -C ${PROJECT_SOURCE_DIR}/druntime/test/${name} all + COMMAND ${GNU_MAKE_BIN} -C ${PROJECT_SOURCE_DIR}/druntime/test/${name} ROOT=${outdir} DMD=${LDMD_EXE_FULL} BUILD=${build} DRUNTIME=${druntime_path_build} DRUNTIMESO=${shared_druntime_path_build} - ${cflags_base} ${linkdl} + SHARED=1 ${cflags_base} ${linkdl} ) set_tests_properties(${fullname} PROPERTIES DEPENDS clean-${fullname}) endforeach() diff --git a/runtime/druntime/test/shared/Makefile b/runtime/druntime/test/shared/Makefile index 88a4c3154d1..561784fdf44 100644 --- a/runtime/druntime/test/shared/Makefile +++ b/runtime/druntime/test/shared/Makefile @@ -1,35 +1,56 @@ -# LDC: druntime DLL supported on Windows -LINK_SHARED:=$(if $(findstring ldmd2,$(DMD)),1,$(if $(findstring $(OS),windows),$(SHARED),1)) +# SHARED (from druntime/Makefile) is `1` for platforms supporting a shared druntime library, otherwise empty +LINK_SHARED:=$(SHARED) include ../common.mak # affected by LINK_SHARED! +ifneq (,$(LINK_SHARED)) + # LDC: disable 3 tests on Mac, 1 on Windows + ifeq (,$(findstring ldmd2,$(DMD))) + # TODO: enable tests on Windows + ifneq (windows,$(OS)) + TESTS:=link load linkD linkDR loadDR host finalize dynamiccast \ + link_linkdep load_linkdep link_loaddep load_loaddep load_13414 + endif + else + TESTS:=link load linkD linkDR loadDR dynamiccast \ + link_linkdep link_loaddep load_loaddep load_13414 + ifneq ($(OS),osx) + # * `host` loads two modules with the same name, which is currently disallowed + # by the (potentially overly eager) module collision detection on OS X. + # * `finalize` fails starting with macOS 10.13, as .dylibs with TLS can't be + # unloaded anymore (https://github.com/ldc-developers/ldc/issues/3002). + # * FIXME: `load_linkdep` + # it might fail because of unimplemented `getDependencies()` in rt.sections_elf_shared + ifeq (windows,$(OS)) + # LDC FIXME: disable `load_linkdep` on Windows - needs `getDependencies()` + TESTS+=host finalize + else + TESTS+=host finalize load_linkdep + endif + endif + endif +endif +# there are extra tests for Windows, not requiring a druntime DLL +ifeq (windows,$(OS)) + TESTS+=loadlibwin dllrefcount dllgc dynamiccast +endif + +DOTIMPLIB:=$(if $(findstring $(OS),windows),.lib,$(DOTDLL)) + .PHONY: all clean +all: $(addprefix $(ROOT)/,$(addsuffix .done,$(TESTS))) $(if $(findstring ldmd2,$(DMD)),$(if $(findstring $(OS),windows),dll_gc_proxy_teardown,),) -ifeq (windows,$(OS)) +ifeq (windows,$(OS)) # extra tests on Windows ifneq (,$(findstring ldmd2,$(DMD))) # LDC: required for executables to implicitly dllimport DLL data symbols DFLAGS+=-dllimport=all +else + ifeq ($(SHARED),1) + DFLAGS+=-version=SharedRuntime + endif endif -TESTS:=loadlibwin dllrefcount dllgc dynamiccast -ifeq ($(SHARED),1) -DFLAGS+=-version=SharedRuntime -endif - -$(ROOT)/%.done: $(ROOT)/%$(DOTEXE) - @echo Testing $* - $(QUIET)$(TIMELIMIT)$< $(RUN_ARGS) - @touch $@ - -$(ROOT)/dynamiccast.done: $(ROOT)/%.done: $(ROOT)/%$(DOTEXE) - @echo Testing $* - $(QUIET)rm -f $(ROOT)/dynamiccast_end{bar,main} - $(QUIET)$(TIMELIMIT)$< $(RUN_ARGS) - $(QUIET)test -f $(ROOT)/dynamiccast_endbar - $(QUIET)test -f $(ROOT)/dynamiccast_endmain - @touch $@ - $(ROOT)/dllrefcount$(DOTEXE): $(SRC)/dllrefcount.d $(QUIET)$(DMD) $(DFLAGS) -of$@ $< @@ -45,10 +66,6 @@ $(ROOT)/dllgc$(DOTEXE): $(SRC)/dllgc.d $(QUIET)$(DMD) $(DFLAGS) -version=DLL -shared -of$(ROOT)/dllgc$(DOTDLL) $< $(QUIET)$(DMD) $(DFLAGS) -of$@ $< -$(ROOT)/dynamiccast$(DOTEXE): $(SRC)/dynamiccast.d - $(QUIET)$(DMD) $(DFLAGS) -version=DLL -shared -of$(ROOT)/dynamiccast$(DOTDLL) $< - $(QUIET)$(DMD) $(DFLAGS) -of$@ $< - # LDC addition: test teardown with separate druntimes, with the DLL using the .exe GC ifneq (,$(findstring ldmd2,$(DMD))) dll_gc_proxy_teardown: DFLAGS+=-link-defaultlib-shared=false -dllimport=none @@ -61,58 +78,34 @@ dll_gc_proxy_teardown: $(SRC)/dll_gc_proxy_teardown.d $(QUIET)$(ROOT)/load_dll_gc_proxy_teardown_nounload$(DOTEXE) endif -# LDC: include Posix tests too endif # Windows -# LDC: disable 3 tests on Mac, 1 on Windows -ifeq (,$(findstring ldmd2,$(DMD))) - TESTS:=link load linkD linkDR loadDR host finalize dynamiccast - TESTS+=link_linkdep load_linkdep link_loaddep load_loaddep load_13414 -else - TESTS+=link load linkD linkDR loadDR dynamiccast - TESTS+=link_linkdep link_loaddep load_loaddep load_13414 - ifneq ($(OS),osx) - # * `host` loads two modules with the same name, which is currently disallowed - # by the (potentially overly eager) module collision detection on OS X. - # * `finalize` fails starting with macOS 10.13, as .dylibs with TLS can't be - # unloaded anymore (https://github.com/ldc-developers/ldc/issues/3002). - # * FIXME: `load_linkdep` - # it might fail because of unimplemented `getDependencies()` in rt.sections_elf_shared - ifneq (,$(findstring win,$(OS))) - # LDC FIXME: disable `load_linkdep` on Windows - needs `getDependencies()` - TESTS+=host finalize - else - TESTS+=host finalize load_linkdep - endif - endif -endif - -EXPORT_DYNAMIC=$(if $(findstring $(OS),linux freebsd dragonflybsd),-L--export-dynamic,) -NO_AS_NEEDED=$(if $(findstring $(OS),linux freebsd dragonflybsd),-L--no-as-needed,) - -all: $(addprefix $(ROOT)/,$(addsuffix .done,$(TESTS))) $(if $(findstring ldmd2,$(DMD)),$(if $(findstring $(OS),windows),dll_gc_proxy_teardown,),) - -$(ROOT)/loadDR.done $(ROOT)/host.done: RUN_ARGS:=$(DRUNTIMESO) - -$(ROOT)/dynamiccast.done: CLEANUP:=rm $(ROOT)/dynamiccast_endmain$(DOTEXE) $(ROOT)/dynamiccast_endbar$(DOTEXE) +$(ROOT)/loadDR.done $(ROOT)/host.done: RUN_ARGS:=$(DRUNTIMESO:.lib=.dll) $(ROOT)/%.done: $(ROOT)/%$(DOTEXE) @echo Testing $* $(QUIET)$(TIMELIMIT)$< $(RUN_ARGS) - $(CLEANUP) + @touch $@ + +$(ROOT)/dynamiccast.done: $(ROOT)/%.done: $(ROOT)/%$(DOTEXE) + @echo Testing $* + $(QUIET)rm -f $(ROOT)/dynamiccast_end{bar,main} + $(QUIET)$(TIMELIMIT)$< $(RUN_ARGS) + $(QUIET)test -f $(ROOT)/dynamiccast_endbar + $(QUIET)test -f $(ROOT)/dynamiccast_endmain @touch $@ $(ROOT)/link$(DOTEXE): $(SRC)/link.d $(ROOT)/lib$(DOTDLL) $(DRUNTIMESO) - $(QUIET)$(DMD) $(DFLAGS) -of$@ $< -L$(ROOT)/lib$(DOTDLL) + $(QUIET)$(DMD) $(DFLAGS) -of$@ $< -L$(ROOT)/lib$(DOTIMPLIB) $(ROOT)/link_linkdep$(DOTEXE): $(SRC)/link_linkdep.d $(ROOT)/lib$(DOTDLL) $(ROOT)/liblinkdep$(DOTDLL) $(DRUNTIMESO) - $(QUIET)$(DMD) $(DFLAGS) -of$@ $< $(LINKFLAGS) -L$(ROOT)/liblinkdep$(DOTDLL) -L$(ROOT)/lib$(DOTDLL) + $(QUIET)$(DMD) $(DFLAGS) -of$@ $< $(LINKFLAGS) -L$(ROOT)/liblinkdep$(DOTIMPLIB) -L$(ROOT)/lib$(DOTIMPLIB) $(ROOT)/load_linkdep$(DOTEXE): $(SRC)/load_linkdep.d $(ROOT)/lib$(DOTDLL) $(ROOT)/liblinkdep$(DOTDLL) $(DRUNTIMESO) $(QUIET)$(DMD) $(DFLAGS) -of$@ $< $(LINKFLAGS) $(LINKDL) $(ROOT)/link_loaddep$(DOTEXE): $(SRC)/link_loaddep.d $(ROOT)/lib$(DOTDLL) $(ROOT)/libloaddep$(DOTDLL) $(DRUNTIMESO) - $(QUIET)$(DMD) $(DFLAGS) -of$@ $< $(LINKFLAGS) -L$(ROOT)/libloaddep$(DOTDLL) + $(QUIET)$(DMD) $(DFLAGS) -of$@ $< $(LINKFLAGS) -L$(ROOT)/libloaddep$(DOTIMPLIB) $(ROOT)/load_loaddep$(DOTEXE): $(SRC)/load_loaddep.d $(ROOT)/lib$(DOTDLL) $(ROOT)/libloaddep$(DOTDLL) $(DRUNTIMESO) $(QUIET)$(DMD) $(DFLAGS) -of$@ $< $(LINKFLAGS) $(LINKDL) @@ -123,33 +116,42 @@ $(ROOT)/load$(DOTEXE) $(ROOT)/finalize$(DOTEXE): $(ROOT)/%$(DOTEXE): $(SRC)/%.d $(ROOT)/load_13414$(DOTEXE): $(ROOT)/%$(DOTEXE): $(SRC)/%.d $(ROOT)/lib_13414$(DOTDLL) $(DRUNTIMESO) $(QUIET)$(DMD) $(DFLAGS) -of$@ $< $(LINKDL) -$(ROOT)/dynamiccast$(DOTEXE): $(SRC)/dynamiccast.d $(ROOT)/dynamiccast$(DOTDLL) $(DRUNTIMESO) +$(ROOT)/dynamiccast$(DOTEXE): $(SRC)/dynamiccast.d $(ROOT)/dynamiccast$(DOTDLL) $(if $(LINK_SHARED),$(DRUNTIMESO),$(DRUNTIME)) $(QUIET)$(DMD) $(DFLAGS) -of$@ $(SRC)/dynamiccast.d $(LINKDL) -$(ROOT)/dynamiccast$(DOTDLL): $(SRC)/dynamiccast.d $(DRUNTIMESO) - $(QUIET)$(DMD) $(DFLAGS) -of$@ $< -version=DLL -fPIC -shared $(LINKDL) +$(ROOT)/dynamiccast$(DOTDLL): $(SRC)/dynamiccast.d $(if $(LINK_SHARED),$(DRUNTIMESO),$(DRUNTIME)) + $(QUIET)$(DMD) $(DFLAGS) -of$@ $< -version=DLL -shared $(LINKDL) + +ifeq (windows,$(OS)) + CC:=cl + CC_OUTFLAG:=/Fe + # we additionally specify the .obj output path (/Fo) to prevent collisions + CC_EXTRAS:= +else + CC_OUTFLAG:=-o + CC_EXTRAS:=$(LDL) -pthread +endif -# TODO: cl.exe flags $(ROOT)/linkD$(DOTEXE): $(SRC)/linkD.c $(ROOT)/lib$(DOTDLL) $(DRUNTIMESO) - $(QUIET)$(CC) $(CFLAGS) -o $@ $< $(ROOT)/lib$(DOTDLL) $(LDL) -pthread + $(QUIET)$(CC) $(CFLAGS) $(CC_OUTFLAG)$@ $(if $(findstring $(OS),windows),/Fo$@.obj,) $< $(ROOT)/lib$(DOTIMPLIB) $(CC_EXTRAS) $(ROOT)/linkDR$(DOTEXE): $(SRC)/linkDR.c $(ROOT)/lib$(DOTDLL) $(DRUNTIMESO) - $(QUIET)$(CC) $(CFLAGS) -o $@ $< $(DRUNTIMESO) $(LDL) -pthread + $(QUIET)$(CC) $(CFLAGS) $(CC_OUTFLAG)$@ $(if $(findstring $(OS),windows),/Fo$@.obj,) $< $(DRUNTIMESO) $(CC_EXTRAS) $(ROOT)/loadDR$(DOTEXE): $(SRC)/loadDR.c $(ROOT)/lib$(DOTDLL) $(DRUNTIMESO) - $(QUIET)$(CC) $(CFLAGS) -o $@ $< $(LDL) -pthread + $(QUIET)$(CC) $(CFLAGS) $(CC_OUTFLAG)$@ $(if $(findstring $(OS),windows),/Fo$@.obj,) $< $(CC_EXTRAS) $(ROOT)/host$(DOTEXE): $(SRC)/host.c $(ROOT)/plugin1$(DOTDLL) $(ROOT)/plugin2$(DOTDLL) - $(QUIET)$(CC) $(CFLAGS) -o $@ $< $(LDL) -pthread + $(QUIET)$(CC) $(CFLAGS) $(CC_OUTFLAG)$@ $(if $(findstring $(OS),windows),/Fo$@.obj,) $< $(CC_EXTRAS) $(ROOT)/liblinkdep$(DOTDLL): $(ROOT)/lib$(DOTDLL) -$(ROOT)/liblinkdep$(DOTDLL): DFLAGS+=-L$(ROOT)/lib$(DOTDLL) +$(ROOT)/liblinkdep$(DOTDLL): DFLAGS+=-L$(ROOT)/lib$(DOTIMPLIB) $(ROOT)/plugin1$(DOTDLL) $(ROOT)/plugin2$(DOTDLL): $(SRC)/plugin.d $(DRUNTIMESO) - $(QUIET)$(DMD) -fPIC -shared $(DFLAGS) -of$@ $< + $(QUIET)$(DMD) -shared $(DFLAGS) -of$@ $< $(ROOT)/%$(DOTDLL): $(SRC)/%.d $(DRUNTIMESO) - $(QUIET)$(DMD) -fPIC -shared $(DFLAGS) -of$@ $< $(LINKDL) + $(QUIET)$(DMD) -shared $(DFLAGS) -of$@ $< $(LINKDL) clean: rm -rf $(GENERATED) diff --git a/runtime/druntime/test/shared/src/dynamiccast.d b/runtime/druntime/test/shared/src/dynamiccast.d index 9bd19de0645..b58bb7efdfa 100644 --- a/runtime/druntime/test/shared/src/dynamiccast.d +++ b/runtime/druntime/test/shared/src/dynamiccast.d @@ -40,17 +40,18 @@ else T getFunc(T)(const(char)* sym) { import core.runtime : Runtime; + import utils : dllExt; version (Windows) { import core.sys.windows.winbase : GetProcAddress; - return cast(T) Runtime.loadLibrary("dynamiccast.dll") + return cast(T) Runtime.loadLibrary("dynamiccast." ~ dllExt) .GetProcAddress(sym); } else version (Posix) { import core.sys.posix.dlfcn : dlsym; - return cast(T) Runtime.loadLibrary("./dynamiccast.so") + return cast(T) Runtime.loadLibrary("./dynamiccast." ~ dllExt) .dlsym(sym); } else static assert(0); diff --git a/runtime/druntime/test/shared/src/host.c b/runtime/druntime/test/shared/src/host.c index c56e783bad5..30f7bee9f02 100644 --- a/runtime/druntime/test/shared/src/host.c +++ b/runtime/druntime/test/shared/src/host.c @@ -5,6 +5,8 @@ #ifdef _WIN32 #define PLUGIN_SO1 "plugin1.dll" +#elif __APPLE__ +#define PLUGIN_SO1 "plugin1.dylib" #else #define PLUGIN_SO1 "plugin1.so" #endif diff --git a/runtime/druntime/test/shared/src/utils.di b/runtime/druntime/test/shared/src/utils.di index 754fbd41362..f6e65438030 100644 --- a/runtime/druntime/test/shared/src/utils.di +++ b/runtime/druntime/test/shared/src/utils.di @@ -2,6 +2,8 @@ module utils; version (Windows) enum dllExt = "dll"; +else version (darwin) + enum dllExt = "dylib"; else enum dllExt = "so"; diff --git a/runtime/druntime/test/shared/src/utils.h b/runtime/druntime/test/shared/src/utils.h index 7bbe23c7420..494a4dda6e4 100644 --- a/runtime/druntime/test/shared/src/utils.h +++ b/runtime/druntime/test/shared/src/utils.h @@ -12,7 +12,11 @@ void *loadSym(void *handle, const char *name) { return GetProcAddress(handle, na #include +#if __APPLE__ +#define LIB_SO "lib.dylib" +#else #define LIB_SO "lib.so" +#endif void *loadLib(const char *name) { return dlopen(name, RTLD_LAZY); } int closeLib(void *handle) { return dlclose(handle) == 0 ? 1 : 0; } From 04c8f0b761348b641f7f2b5f692969339cf9532d Mon Sep 17 00:00:00 2001 From: "richard (rikki) andrew cattermole" Date: Fri, 19 Jan 2024 09:37:59 +1300 Subject: [PATCH 191/215] Make core.internal.atomic handle floats (dmd) --- runtime/druntime/src/core/atomic.d | 44 +- runtime/druntime/src/core/internal/atomic.d | 529 ++++++++------------ runtime/druntime/src/core/stdc/stdatomic.d | 209 ++++++-- 3 files changed, 379 insertions(+), 403 deletions(-) diff --git a/runtime/druntime/src/core/atomic.d b/runtime/druntime/src/core/atomic.d index ff7f7abf0c2..899e0b054ba 100644 --- a/runtime/druntime/src/core/atomic.d +++ b/runtime/druntime/src/core/atomic.d @@ -88,14 +88,7 @@ enum MemoryOrder T atomicLoad(MemoryOrder ms = MemoryOrder.seq, T)(auto ref return scope const T val) pure nothrow @nogc @trusted if (!is(T == shared U, U) && !is(T == shared inout U, U) && !is(T == shared const U, U)) { - static if (__traits(isFloating, T)) - { - alias IntTy = IntForFloat!T; - IntTy r = core.internal.atomic.atomicLoad!ms(cast(IntTy*)&val); - return *cast(T*)&r; - } - else - return core.internal.atomic.atomicLoad!ms(cast(T*)&val); + return core.internal.atomic.atomicLoad!ms(cast(T*)&val); } /// Ditto @@ -137,13 +130,7 @@ void atomicStore(MemoryOrder ms = MemoryOrder.seq, T, V)(ref T val, V newval) pu // resolve implicit conversions T arg = newval; - static if (__traits(isFloating, T)) - { - alias IntTy = IntForFloat!T; - core.internal.atomic.atomicStore!ms(cast(IntTy*)&val, *cast(IntTy*)&arg); - } - else - core.internal.atomic.atomicStore!ms(&val, arg); + core.internal.atomic.atomicStore!ms(&val, arg); } /// Ditto @@ -246,14 +233,7 @@ in (atomicPtrIsProperlyAligned(here), "Argument `here` is not properly aligned") // resolve implicit conversions T arg = exchangeWith; - static if (__traits(isFloating, T)) - { - alias IntTy = IntForFloat!T; - IntTy r = core.internal.atomic.atomicExchange!ms(cast(IntTy*)here, *cast(IntTy*)&arg); - return *cast(shared(T)*)&r; - } - else - return core.internal.atomic.atomicExchange!ms(here, arg); + return core.internal.atomic.atomicExchange!ms(here, arg); } /// Ditto @@ -314,14 +294,7 @@ template cas(MemoryOrder succ = MemoryOrder.seq, MemoryOrder fail = MemoryOrder. const T arg1 = ifThis; T arg2 = writeThis; - static if (__traits(isFloating, T)) - { - alias IntTy = IntForFloat!T; - return atomicCompareExchangeStrongNoResult!(succ, fail)( - cast(IntTy*)here, *cast(IntTy*)&arg1, *cast(IntTy*)&arg2); - } - else - return atomicCompareExchangeStrongNoResult!(succ, fail)(here, arg1, arg2); + return atomicCompareExchangeStrongNoResult!(succ, fail)(here, arg1, arg2); } /// Compare-and-set for shared value type @@ -364,14 +337,7 @@ template cas(MemoryOrder succ = MemoryOrder.seq, MemoryOrder fail = MemoryOrder. // resolve implicit conversions T arg1 = writeThis; - static if (__traits(isFloating, T)) - { - alias IntTy = IntForFloat!T; - return atomicCompareExchangeStrong!(succ, fail)( - cast(IntTy*)here, cast(IntTy*)ifThis, *cast(IntTy*)&writeThis); - } - else - return atomicCompareExchangeStrong!(succ, fail)(here, ifThis, writeThis); + return atomicCompareExchangeStrong!(succ, fail)(here, ifThis, writeThis); } /// Compare and exchange for mixed-`shared`ness types diff --git a/runtime/druntime/src/core/internal/atomic.d b/runtime/druntime/src/core/internal/atomic.d index cc28e123f17..b864357d977 100644 --- a/runtime/druntime/src/core/internal/atomic.d +++ b/runtime/druntime/src/core/internal/atomic.d @@ -57,113 +57,102 @@ version (DigitalMars) static assert(order != MemoryOrder.rel && order != MemoryOrder.acq_rel, "invalid MemoryOrder for atomicLoad()"); + // We place some storage on the stack, + // get a pointer to that (which is also stored on the stack) + // and then store the result of the load into the storage. + // Finally returning it. + // Anything other than this is calling convention specific, + // and that is very fail heavy. + size_t[2] storage = void; + size_t* resultValuePtr = cast(size_t*)&storage[0]; + static if (T.sizeof == size_t.sizeof * 2) { version (D_InlineAsm_X86) { asm pure nothrow @nogc @trusted { + push EBX; // call preserved push EDI; - push EBX; + mov EBX, 0; mov ECX, 0; mov EAX, 0; mov EDX, 0; + mov EDI, src; lock; cmpxchg8b [EDI]; - pop EBX; + + lea EBX, resultValuePtr; + mov EBX, [EBX]; + mov [EBX], EAX; + mov [EBX + size_t.sizeof], EDX; + pop EDI; + pop EBX; } } else version (D_InlineAsm_X86_64) { - version (Windows) + asm pure nothrow @nogc @trusted { - static if (RegisterReturn!T) - { - enum SrcPtr = SizedReg!CX; - enum RetPtr = null; - } - else - { - enum SrcPtr = SizedReg!DX; - enum RetPtr = SizedReg!CX; - } + push RBX; // call preserved - mixin (simpleFormat(q{ - asm pure nothrow @nogc @trusted - { - naked; - push RBX; - mov R8, %0; - ?1 mov R9, %1; - mov RBX, 0; - mov RCX, 0; - mov RAX, 0; - mov RDX, 0; - lock; cmpxchg16b [R8]; - ?1 mov [R9], RAX; - ?1 mov 8[R9], RDX; - pop RBX; - ret; - } - }, [SrcPtr, RetPtr])); - } - else - { - asm pure nothrow @nogc @trusted - { - naked; - push RBX; - mov RBX, 0; - mov RCX, 0; - mov RAX, 0; - mov RDX, 0; - lock; cmpxchg16b [RDI]; - pop RBX; - ret; - } + mov RBX, 0; + mov RCX, 0; + mov RAX, 0; + mov RDX, 0; + + mov R8, src; + lock; cmpxchg16b [R8]; + + lea RBX, resultValuePtr; + mov RBX, [RBX]; + mov [RBX], RAX; + mov [RBX + size_t.sizeof], RDX; + + pop RBX; } } + else + static assert(0, "Operation not supported"); + + return *cast(inout(T)*)resultValuePtr; } else static if (needsLoadBarrier!order) { version (D_InlineAsm_X86) { - enum SrcReg = SizedReg!CX; - enum ZeroReg = SizedReg!(DX, T); - enum ResReg = SizedReg!(AX, T); - - mixin (simpleFormat(q{ - asm pure nothrow @nogc @trusted - { - mov %1, 0; - mov %2, 0; - mov %0, src; - lock; cmpxchg [%0], %1; - } - }, [SrcReg, ZeroReg, ResReg])); } else version (D_InlineAsm_X86_64) { - version (Windows) - enum SrcReg = SizedReg!CX; - else - enum SrcReg = SizedReg!DI; - enum ZeroReg = SizedReg!(DX, T); - enum ResReg = SizedReg!(AX, T); - - mixin (simpleFormat(q{ - asm pure nothrow @nogc @trusted - { - naked; - mov %1, 0; - mov %2, 0; - lock; cmpxchg [%0], %1; - ret; - } - }, [SrcReg, ZeroReg, ResReg])); } + else + static assert(0, "Operation not supported"); + + enum SrcReg = SizedReg!CX; + enum ZeroReg = SizedReg!(DX, T); + enum ResReg = SizedReg!(AX, T); + enum TemporaryReg = SizedReg!(BX); + + mixin (simpleFormat(q{ + asm pure nothrow @nogc @trusted + { + push %3; // call preserved + + mov %1, 0; + mov %2, 0; + mov %0, src; + lock; cmpxchg [%0], %1; + lea %3, resultValuePtr; + mov %3, [%3]; + mov [%3], %2; + + pop %3; + } + }, [SrcReg, ZeroReg, ResReg, TemporaryReg])); + + return *cast(inout(T)*)resultValuePtr; } else return *src; @@ -296,49 +285,37 @@ version (DigitalMars) if (CanCAS!T) { static assert(order != MemoryOrder.acq, "Invalid MemoryOrder for atomicExchange()"); + // We place some storage on the stack, + // this storage and cast it to appropriete type. + // This is calling convention agnostic. + size_t storage = void; version (D_InlineAsm_X86) { - static assert(T.sizeof <= 4, "64bit atomicExchange not supported on 32bit target." ); - - enum DestReg = SizedReg!CX; - enum ValReg = SizedReg!(AX, T); - - mixin (simpleFormat(q{ - asm pure nothrow @nogc @trusted - { - mov %1, value; - mov %0, dest; - xchg [%0], %1; - } - }, [DestReg, ValReg])); + static assert(T.sizeof <= 4, "64bit atomicExchange not supported on 32bit target."); } else version (D_InlineAsm_X86_64) { - version (Windows) - { - enum DestReg = SizedReg!DX; - enum ValReg = SizedReg!(CX, T); - } - else + } + else + static assert(0, "Operation not supported"); + + enum DestReg = SizedReg!CX; + enum ValReg = SizedReg!(AX, T); + + mixin (simpleFormat(q{ + asm pure nothrow @nogc @trusted { - enum DestReg = SizedReg!SI; - enum ValReg = SizedReg!(DI, T); + mov %1, value; + mov %0, dest; + lock; xchg [%0], %1; + + lea %0, storage; + mov [%0], %1; } - enum ResReg = result ? SizedReg!(AX, T) : null; + }, [DestReg, ValReg])); - mixin (simpleFormat(q{ - asm pure nothrow @nogc @trusted - { - naked; - xchg [%0], %1; - ?2 mov %2, %1; - ret; - } - }, [DestReg, ValReg, ResReg])); - } - else - static assert (false, "Unsupported architecture."); + return *cast(T*)&storage; } alias atomicCompareExchangeWeak = atomicCompareExchangeStrong; @@ -349,143 +326,99 @@ version (DigitalMars) static assert(fail != MemoryOrder.rel && fail != MemoryOrder.acq_rel, "Invalid fail MemoryOrder for atomicCompareExchangeStrong()"); static assert (succ >= fail, "The first MemoryOrder argument for atomicCompareExchangeStrong() cannot be weaker than the second argument"); + bool success; - version (D_InlineAsm_X86) + static if (T.sizeof == size_t.sizeof * 2) { - static if (T.sizeof <= 4) - { - enum DestAddr = SizedReg!CX; - enum CmpAddr = SizedReg!DI; - enum Val = SizedReg!(DX, T); - enum Cmp = SizedReg!(AX, T); + // some values simply cannot be loa'd here, so we'll use an intermediary pointer that we can move instead + T* valuePointer = &value; - mixin (simpleFormat(q{ - asm pure nothrow @nogc @trusted - { - push %1; - mov %2, value; - mov %1, compare; - mov %3, [%1]; - mov %0, dest; - lock; cmpxchg [%0], %2; - mov [%1], %3; - setz AL; - pop %1; - } - }, [DestAddr, CmpAddr, Val, Cmp])); - } - else static if (T.sizeof == 8) + version (D_InlineAsm_X86) { asm pure nothrow @nogc @trusted { + push EBX; // call preserved push EDI; - push EBX; - lea EDI, value; + + mov EDI, valuePointer; // value mov EBX, [EDI]; - mov ECX, 4[EDI]; - mov EDI, compare; + mov ECX, [EDI + size_t.sizeof]; + mov EDI, compare; // [compare] mov EAX, [EDI]; - mov EDX, 4[EDI]; + mov EDX, [EDI + size_t.sizeof]; + mov EDI, dest; lock; cmpxchg8b [EDI]; + + setz success; mov EDI, compare; mov [EDI], EAX; - mov 4[EDI], EDX; - setz AL; - pop EBX; + mov [EDI + size_t.sizeof], EDX; + pop EDI; + pop EBX; } } - else - static assert(T.sizeof <= 8, "128bit atomicCompareExchangeStrong not supported on 32bit target." ); - } - else version (D_InlineAsm_X86_64) - { - static if (T.sizeof <= 8) + else version (D_InlineAsm_X86_64) { - version (Windows) - { - enum DestAddr = SizedReg!R8; - enum CmpAddr = SizedReg!DX; - enum Val = SizedReg!(CX, T); - } - else + asm pure nothrow @nogc @trusted { - enum DestAddr = SizedReg!DX; - enum CmpAddr = SizedReg!SI; - enum Val = SizedReg!(DI, T); - } - enum Res = SizedReg!(AX, T); + push RBX; // call preserved - mixin (simpleFormat(q{ - asm pure nothrow @nogc @trusted - { - naked; - mov %3, [%1]; - lock; cmpxchg [%0], %2; - jne compare_fail; - mov AL, 1; - ret; - compare_fail: - mov [%1], %3; - xor AL, AL; - ret; - } - }, [DestAddr, CmpAddr, Val, Res])); + mov R8, valuePointer; // value + mov RBX, [R8]; + mov RCX, [R8 + size_t.sizeof]; + mov R8, compare; // [compare] + mov RAX, [R8]; + mov RDX, [R8 + size_t.sizeof]; + + mov R8, dest; + lock; cmpxchg16b [R8]; + + setz success; + mov R8, compare; + mov [R8], RAX; + mov [R8 + size_t.sizeof], RDX; + + pop RBX; + } } else + static assert(0, "Operation not supported"); + } + else + { + version (D_InlineAsm_X86) { - version (Windows) - { - asm pure nothrow @nogc @trusted - { - naked; - push RBX; - mov R9, RDX; - mov RAX, [RDX]; - mov RDX, 8[RDX]; - mov RBX, [RCX]; - mov RCX, 8[RCX]; - lock; cmpxchg16b [R8]; - pop RBX; - jne compare_fail; - mov AL, 1; - ret; - compare_fail: - mov [R9], RAX; - mov 8[R9], RDX; - xor AL, AL; - ret; - } - } - else + } + else version (D_InlineAsm_X86_64) + { + } + else + static assert(0, "Operation not supported"); + + enum SrcReg = SizedReg!CX; + enum ValueReg = SizedReg!(DX, T); + enum CompareReg = SizedReg!(AX, T); + + mixin (simpleFormat(q{ + asm pure nothrow @nogc @trusted { - asm pure nothrow @nogc @trusted - { - naked; - push RBX; - mov R8, RCX; - mov R9, RDX; - mov RAX, [RDX]; - mov RDX, 8[RDX]; - mov RBX, RDI; - mov RCX, RSI; - lock; cmpxchg16b [R8]; - pop RBX; - jne compare_fail; - mov AL, 1; - ret; - compare_fail: - mov [R9], RAX; - mov 8[R9], RDX; - xor AL, AL; - ret; - } + mov %1, value; + mov %0, compare; + mov %2, [%0]; + + mov %0, dest; + lock; cmpxchg [%0], %1; + + setz success; + mov %0, compare; + mov [%0], %2; } - } + }, [SrcReg, ValueReg, CompareReg])); } - else - static assert (false, "Unsupported architecture."); + + return success; } alias atomicCompareExchangeWeakNoResult = atomicCompareExchangeStrongNoResult; @@ -496,115 +429,91 @@ version (DigitalMars) static assert(fail != MemoryOrder.rel && fail != MemoryOrder.acq_rel, "Invalid fail MemoryOrder for atomicCompareExchangeStrongNoResult()"); static assert (succ >= fail, "The first MemoryOrder argument for atomicCompareExchangeStrongNoResult() cannot be weaker than the second argument"); + bool success; - version (D_InlineAsm_X86) + static if (T.sizeof == size_t.sizeof * 2) { - static if (T.sizeof <= 4) - { - enum DestAddr = SizedReg!CX; - enum Cmp = SizedReg!(AX, T); - enum Val = SizedReg!(DX, T); + // some values simply cannot be loa'd here, so we'll use an intermediary pointer that we can move instead + T* valuePointer = &value; + const(T)* comparePointer = &compare; - mixin (simpleFormat(q{ - asm pure nothrow @nogc @trusted - { - mov %2, value; - mov %1, compare; - mov %0, dest; - lock; cmpxchg [%0], %2; - setz AL; - } - }, [DestAddr, Cmp, Val])); - } - else static if (T.sizeof == 8) + version (D_InlineAsm_X86) { asm pure nothrow @nogc @trusted { + push EBX; // call preserved push EDI; - push EBX; - lea EDI, value; + + mov EDI, valuePointer; // value mov EBX, [EDI]; - mov ECX, 4[EDI]; - lea EDI, compare; + mov ECX, [EDI + size_t.sizeof]; + mov EDI, comparePointer; // compare mov EAX, [EDI]; - mov EDX, 4[EDI]; + mov EDX, [EDI + size_t.sizeof]; + mov EDI, dest; lock; cmpxchg8b [EDI]; - setz AL; - pop EBX; + + setz success; + pop EDI; + pop EBX; } } - else - static assert(T.sizeof <= 8, "128bit atomicCompareExchangeStrong not supported on 32bit target." ); - } - else version (D_InlineAsm_X86_64) - { - static if (T.sizeof <= 8) + else version (D_InlineAsm_X86_64) { - version (Windows) - { - enum DestAddr = SizedReg!R8; - enum Cmp = SizedReg!(DX, T); - enum Val = SizedReg!(CX, T); - } - else + asm pure nothrow @nogc @trusted { - enum DestAddr = SizedReg!DX; - enum Cmp = SizedReg!(SI, T); - enum Val = SizedReg!(DI, T); - } - enum AXReg = SizedReg!(AX, T); + push RBX; // call preserved - mixin (simpleFormat(q{ - asm pure nothrow @nogc @trusted - { - naked; - mov %3, %1; - lock; cmpxchg [%0], %2; - setz AL; - ret; - } - }, [DestAddr, Cmp, Val, AXReg])); + mov R8, valuePointer; // value + mov RBX, [R8]; + mov RCX, [R8 + size_t.sizeof]; + mov R8, comparePointer; // compare + mov RAX, [R8]; + mov RDX, [R8 + size_t.sizeof]; + + mov R8, dest; + lock; cmpxchg16b [R8]; + + setz success; + + pop RBX; + } } else + static assert(0, "Operation not supported"); + } + else + { + version (D_InlineAsm_X86) { - version (Windows) - { - asm pure nothrow @nogc @trusted - { - naked; - push RBX; - mov RAX, [RDX]; - mov RDX, 8[RDX]; - mov RBX, [RCX]; - mov RCX, 8[RCX]; - lock; cmpxchg16b [R8]; - setz AL; - pop RBX; - ret; - } - } - else + } + else version (D_InlineAsm_X86_64) + { + } + else + static assert(0, "Operation not supported"); + + enum SrcReg = SizedReg!CX; + enum ValueReg = SizedReg!(DX, T); + enum CompareReg = SizedReg!(AX, T); + + mixin (simpleFormat(q{ + asm pure nothrow @nogc @trusted { - asm pure nothrow @nogc @trusted - { - naked; - push RBX; - mov RAX, RDX; - mov RDX, RCX; - mov RBX, RDI; - mov RCX, RSI; - lock; cmpxchg16b [R8]; - setz AL; - pop RBX; - ret; - } + mov %1, value; + mov %2, compare; + + mov %0, dest; + lock; cmpxchg [%0], %1; + + setz success; } - } + }, [SrcReg, ValueReg, CompareReg])); } - else - static assert (false, "Unsupported architecture."); + + return success; } void atomicFence(MemoryOrder order = MemoryOrder.seq)() pure nothrow @nogc @trusted @@ -1091,10 +1000,10 @@ version (Windows) enum RegisterReturn(T) = is(T : U[], U) || is(T : R delegate(A), R, A...); } -enum CanCAS(T) = is(T : ulong) || +enum CanCAS(T) = (__traits(isScalar, T) && // check to see if it is some kind of basic type like an integer/float/pointer + T.sizeof <= size_t.sizeof * 2) || // make sure if it is, that it is no more than 2 words is(T == class) || is(T == interface) || - is(T : U*, U) || is(T : U[], U) || is(T : R delegate(A), R, A...) || (is(T == struct) && __traits(isPOD, T) && diff --git a/runtime/druntime/src/core/stdc/stdatomic.d b/runtime/druntime/src/core/stdc/stdatomic.d index 96f99a4a72f..b2736bc4d39 100644 --- a/runtime/druntime/src/core/stdc/stdatomic.d +++ b/runtime/druntime/src/core/stdc/stdatomic.d @@ -7,6 +7,8 @@ * * $(NOTE The D shared type qualifier is the closest to the _Atomic type qualifier from C. It may be changed from shared in the future.) * + * $(NOTE Fail memory order is currently ignored due to limitations with internal implementation of atomics.) + * * Copyright: Copyright Richard (Rikki) Andrew Cattermole 2023. * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) * Authors: Richard (Rikki) Andrew cattermole @@ -194,7 +196,7 @@ bool atomic_flag_test_and_set_impl()(atomic_flag* obj) } /// -unittest +@trusted unittest { atomic_flag flag; assert(!atomic_flag_test_and_set_impl(&flag)); @@ -229,7 +231,7 @@ bool atomic_flag_test_and_set_explicit_impl()(atomic_flag* obj, memory_order ord } /// -unittest +@trusted unittest { atomic_flag flag; assert(!atomic_flag_test_and_set_explicit_impl(&flag, memory_order.memory_order_seq_cst)); @@ -252,6 +254,9 @@ unittest { shared int val; atomic_init(val, 2); + + shared float valF; + atomic_init(valF, 3.2); } /// No-op function, doesn't apply to D @@ -412,14 +417,17 @@ pragma(inline, true) void atomic_store_impl(A, C)(shared(A)* obj, C desired) @trusted { assert(obj !is null); - atomicStore(obj, cast(A)desired); + atomicStore(cast(A*)obj, cast(A)desired); } /// -unittest +@trusted unittest { shared(int) obj; atomic_store_impl(&obj, 3); + + shared(float) objF; + atomic_store_impl(&objF, 3.21); } /// @@ -431,31 +439,34 @@ void atomic_store_explicit_impl(A, C)(shared(A)* obj, C desired, memory_order or final switch (order) { case memory_order.memory_order_relaxed: - atomicStore!(memory_order.memory_order_relaxed)(obj, cast(A)desired); + atomicStore!(memory_order.memory_order_relaxed)(cast(A*)obj, cast(A)desired); break; case memory_order.memory_order_acquire: case memory_order.memory_order_acq_rel: // Ideally this would error at compile time but alas it is not an intrinsic. // Note: this is not a valid memory order for this operation. - atomicStore!(memory_order.memory_order_release)(obj, cast(A)desired); + atomicStore!(memory_order.memory_order_release)(cast(A*)obj, cast(A)desired); break; case memory_order.memory_order_release: - atomicStore!(memory_order.memory_order_release)(obj, cast(A)desired); + atomicStore!(memory_order.memory_order_release)(cast(A*)obj, cast(A)desired); break; case memory_order.memory_order_seq_cst: - atomicStore!(memory_order.memory_order_seq_cst)(obj, cast(A)desired); + atomicStore!(memory_order.memory_order_seq_cst)(cast(A*)obj, cast(A)desired); break; } } /// -unittest +@trusted unittest { shared(int) obj; atomic_store_explicit_impl(&obj, 3, memory_order.memory_order_seq_cst); + + shared(float) objF; + atomic_store_explicit_impl(&objF, 3.21, memory_order.memory_order_seq_cst); } /// @@ -463,14 +474,24 @@ pragma(inline, true) A atomic_load_impl(A)(const shared(A)* obj) @trusted { assert(obj !is null); - return atomicLoad(cast(shared(A)*)obj); + return atomicLoad(cast(A*)obj); } /// -unittest +@trusted unittest { shared(int) obj = 3; assert(atomic_load_impl(&obj) == 3); + + shared(float) objF = 3.5; + assert(atomic_load_impl(&objF) > 3); + + static struct S2 + { + size_t[2] values; + } + shared(S2) objS2 = {[1, 2]}; + assert(atomic_load_impl(&objS2).values == [1, 2]); } /// @@ -482,27 +503,30 @@ A atomic_load_explicit_impl(A)(const shared(A)* obj, memory_order order) @truste final switch (order) { case memory_order.memory_order_relaxed: - return atomicLoad!(memory_order.memory_order_relaxed)(obj); + return atomicLoad!(memory_order.memory_order_relaxed)(cast(A*)obj); case memory_order.memory_order_acquire: - return atomicLoad!(memory_order.memory_order_acquire)(obj); + return atomicLoad!(memory_order.memory_order_acquire)(cast(A*)obj); case memory_order.memory_order_release: case memory_order.memory_order_acq_rel: // Ideally this would error at compile time but alas it is not an intrinsic. // Note: this is not a valid memory order for this operation. - return atomicLoad!(memory_order.memory_order_acquire)(obj); + return atomicLoad!(memory_order.memory_order_acquire)(cast(A*)obj); case memory_order.memory_order_seq_cst: - return atomicLoad!(memory_order.memory_order_seq_cst)(obj); + return atomicLoad!(memory_order.memory_order_seq_cst)(cast(A*)obj); } } /// -unittest +@trusted unittest { shared(int) obj = 3; assert(atomic_load_explicit_impl(&obj, memory_order.memory_order_seq_cst) == 3); + + shared(float) objF = 3.5; + assert(atomic_load_explicit_impl(&objF, memory_order.memory_order_seq_cst) > 3); } /// @@ -510,14 +534,17 @@ pragma(inline, true) A atomic_exchange_impl(A, C)(shared(A)* obj, C desired) @trusted { assert(obj !is null); - return atomicExchange(cast(shared(A)*)obj, cast(A)desired); + return atomicExchange(cast(A*)obj, cast(A)desired); } /// -unittest +@trusted unittest { shared(int) obj = 3; assert(atomic_exchange_impl(&obj, 2) == 3); + + shared(float) objF = 3; + assert(atomic_exchange_impl(&objF, 2.1) > 2.5); } /// @@ -529,121 +556,178 @@ A atomic_exchange_explicit_impl(A, C)(shared(A)* obj, C desired, memory_order or final switch (order) { case memory_order.memory_order_relaxed: - return atomicExchange!(memory_order.memory_order_relaxed)(obj, cast(A)desired); + return atomicExchange!(memory_order.memory_order_relaxed)(cast(A*)obj, cast(A)desired); case memory_order.memory_order_acquire: // Ideally this would error at compile time but alas it is not an intrinsic. // Note: this is not a valid memory order for this operation. - return atomicExchange!(memory_order.memory_order_seq_cst)(obj, cast(A)desired); + return atomicExchange!(memory_order.memory_order_seq_cst)(cast(A*)obj, cast(A)desired); case memory_order.memory_order_release: - return atomicExchange!(memory_order.memory_order_release)(obj, cast(A)desired); + return atomicExchange!(memory_order.memory_order_release)(cast(A*)obj, cast(A)desired); case memory_order.memory_order_acq_rel: - return atomicExchange!(memory_order.memory_order_acq_rel)(obj, cast(A)desired); + return atomicExchange!(memory_order.memory_order_acq_rel)(cast(A*)obj, cast(A)desired); case memory_order.memory_order_seq_cst: - return atomicExchange!(memory_order.memory_order_seq_cst)(obj, cast(A)desired); + return atomicExchange!(memory_order.memory_order_seq_cst)(cast(A*)obj, cast(A)desired); } } /// -unittest +@trusted unittest { shared(int) obj = 3; assert(atomic_exchange_explicit_impl(&obj, 2, memory_order.memory_order_seq_cst) == 3); + + shared(float) objF = 1.5; + assert(atomic_exchange_explicit_impl(&objF, 2.1, memory_order.memory_order_seq_cst) < 2); } /// pragma(inline, true) -bool atomic_compare_exchange_strong_impl(A, C)(shared(A)* obj, A* expected, C desired) @trusted +bool atomic_compare_exchange_strong_impl(A, B, C)(shared(A)* obj, B* expected, C desired) @trusted { - return atomicCompareExchangeStrong(cast(A*)obj, expected, cast(A)desired); + static assert(is(shared(B) : A), "Both expected and object must be the same type"); + return atomicCompareExchangeStrong(cast(B*)obj, expected, cast(B)desired); } /// -unittest +@trusted unittest { shared(int) obj = 3; int expected = 3; assert(atomic_compare_exchange_strong_impl(&obj, &expected, 2)); } +/// +@trusted unittest +{ + shared(float) obj = 3; + float expected = 3; + assert(atomic_compare_exchange_strong_impl(&obj, &expected, 2.1)); +} + /// pragma(inline, true) -bool atomic_compare_exchange_weak_impl(A, C)(shared(A)* obj, A* expected, C desired) @trusted +bool atomic_compare_exchange_weak_impl(A, B, C)(shared(A)* obj, B* expected, C desired) @trusted { - return atomicCompareExchangeStrong(cast(A*)obj, expected, cast(A)desired); + static assert(is(shared(B) : A), "Both expected and object must be the same type"); + return atomicCompareExchangeWeak(cast(B*)obj, expected, cast(B)desired); } /// -unittest +@trusted unittest { shared(int) obj = 3; int expected = 3; static assert(__traits(compiles, {atomic_compare_exchange_weak_impl(&obj, &expected, 2);})); } +/// +@trusted unittest +{ + shared(float) obj = 3; + float expected = 3; + static assert(__traits(compiles, {atomic_compare_exchange_weak_impl(&obj, &expected, 2.1);})); +} + /// pragma(inline, true) -bool atomic_compare_exchange_strong_explicit_impl(A, C)(shared(A)* obj, A* expected, C desired, memory_order succ, memory_order /*fail*/) @trusted +bool atomic_compare_exchange_strong_explicit_impl(A, B, C)(shared(A)* obj, B* expected, C desired, memory_order succ, memory_order fail) @trusted { + static assert(is(shared(B) : A), "Both expected and object must be the same type"); assert(obj !is null); // NOTE: To not have to deal with all invalid cases, the failure model is ignored for now. final switch(succ) { case memory_order.memory_order_relaxed: - return atomicCompareExchangeStrong!(memory_order.memory_order_relaxed, memory_order.memory_order_relaxed)(cast(A*)obj, expected, cast(A)desired); + return atomicCompareExchangeStrong!(memory_order.memory_order_relaxed, memory_order.memory_order_relaxed)(cast(B*)obj, expected, cast(B)desired); case memory_order.memory_order_acquire: - return atomicCompareExchangeStrong!(memory_order.memory_order_acquire, memory_order.memory_order_relaxed)(cast(A*)obj, expected, cast(A)desired); + return atomicCompareExchangeStrong!(memory_order.memory_order_acquire, memory_order.memory_order_relaxed)(cast(B*)obj, expected, cast(B)desired); case memory_order.memory_order_release: - return atomicCompareExchangeStrong!(memory_order.memory_order_release, memory_order.memory_order_relaxed)(cast(A*)obj, expected, cast(A)desired); + return atomicCompareExchangeStrong!(memory_order.memory_order_release, memory_order.memory_order_relaxed)(cast(B*)obj, expected, cast(B)desired); case memory_order.memory_order_acq_rel: - return atomicCompareExchangeStrong!(memory_order.memory_order_acq_rel, memory_order.memory_order_relaxed)(cast(A*)obj, expected, cast(A)desired); + return atomicCompareExchangeStrong!(memory_order.memory_order_acq_rel, memory_order.memory_order_relaxed)(cast(B*)obj, expected, cast(B)desired); case memory_order.memory_order_seq_cst: - return atomicCompareExchangeStrong!(memory_order.memory_order_seq_cst, memory_order.memory_order_relaxed)(cast(A*)obj, expected, cast(A)desired); + return atomicCompareExchangeStrong!(memory_order.memory_order_seq_cst, memory_order.memory_order_relaxed)(cast(B*)obj, expected, cast(B)desired); } } /// -unittest +@trusted unittest { shared(int) obj = 3; int expected = 3; assert(atomic_compare_exchange_strong_explicit_impl(&obj, &expected, 2, memory_order.memory_order_seq_cst, memory_order.memory_order_seq_cst)); } +/// +@trusted unittest +{ + shared(size_t[2]) obj = [3, 4]; + size_t[2] expected = [3, 4]; + size_t[2] toSwap = [1, 2]; + assert(atomic_compare_exchange_strong_explicit_impl(&obj, &expected, toSwap, memory_order.memory_order_seq_cst, memory_order.memory_order_seq_cst)); +} + +/// +@trusted unittest +{ + shared(float) obj = 3; + float expected = 3; + assert(atomic_compare_exchange_strong_explicit_impl(&obj, &expected, 2.1, memory_order.memory_order_seq_cst, memory_order.memory_order_seq_cst)); +} + /// pragma(inline, true) -bool atomic_compare_exchange_weak_explicit_impl(A, C)(shared(A)* obj, A* expected, C desired, memory_order succ, memory_order /*fail*/) @trusted +bool atomic_compare_exchange_weak_explicit_impl(A, B, C)(shared(A)* obj, B* expected, C desired, memory_order succ, memory_order fail) @trusted { + static assert(is(shared(B) : A), "Both expected and object must be the same type"); assert(obj !is null); // NOTE: To not have to deal with all invalid cases, the failure model is ignored for now. final switch(succ) { case memory_order.memory_order_relaxed: - return atomicCompareExchangeWeak!(memory_order.memory_order_relaxed, memory_order.memory_order_relaxed)(cast(A*)obj, expected, cast(A)desired); + return atomicCompareExchangeWeak!(memory_order.memory_order_relaxed, memory_order.memory_order_relaxed)(cast(B*)obj, expected, cast(B)desired); case memory_order.memory_order_acquire: - return atomicCompareExchangeWeak!(memory_order.memory_order_acquire, memory_order.memory_order_relaxed)(cast(A*)obj, expected, cast(A)desired); + return atomicCompareExchangeWeak!(memory_order.memory_order_acquire, memory_order.memory_order_relaxed)(cast(B*)obj, expected, cast(B)desired); case memory_order.memory_order_release: - return atomicCompareExchangeWeak!(memory_order.memory_order_release, memory_order.memory_order_relaxed)(cast(A*)obj, expected, cast(A)desired); + return atomicCompareExchangeWeak!(memory_order.memory_order_release, memory_order.memory_order_relaxed)(cast(B*)obj, expected, cast(B)desired); case memory_order.memory_order_acq_rel: - return atomicCompareExchangeWeak!(memory_order.memory_order_acq_rel, memory_order.memory_order_relaxed)(cast(A*)obj, expected, cast(A)desired); + return atomicCompareExchangeWeak!(memory_order.memory_order_acq_rel, memory_order.memory_order_relaxed)(cast(B*)obj, expected, cast(B)desired); case memory_order.memory_order_seq_cst: - return atomicCompareExchangeWeak!(memory_order.memory_order_seq_cst, memory_order.memory_order_relaxed)(cast(A*)obj, expected, cast(A)desired); + return atomicCompareExchangeWeak!(memory_order.memory_order_seq_cst, memory_order.memory_order_relaxed)(cast(B*)obj, expected, cast(B)desired); } } /// -unittest +@trusted unittest { shared(int) obj = 3; int expected = 3; atomic_compare_exchange_weak_explicit_impl(&obj, &expected, 2, memory_order.memory_order_seq_cst, memory_order.memory_order_seq_cst); } +/// +@trusted unittest +{ + shared(size_t[2]) obj = [3, 4]; + size_t[2] expected = [3, 4]; + size_t[2] toSwap = [1, 2]; + assert(atomic_compare_exchange_weak_explicit_impl(&obj, &expected, toSwap, memory_order.memory_order_seq_cst, memory_order.memory_order_seq_cst)); +} + +/// +@trusted unittest +{ + shared(float) obj = 3; + float expected = 3; + atomic_compare_exchange_weak_explicit_impl(&obj, &expected, 2, memory_order.memory_order_seq_cst, memory_order.memory_order_seq_cst); +} + /// pragma(inline, true) A atomic_fetch_add_impl(A, M)(shared(A)* obj, M arg) @trusted @@ -653,11 +737,15 @@ A atomic_fetch_add_impl(A, M)(shared(A)* obj, M arg) @trusted } /// -unittest +@trusted unittest { shared(int) val; atomic_fetch_add_impl(&val, 3); assert(atomic_load_impl(&val) == 3); + + shared(float) valF = 0.5; + atomic_fetch_add_impl(&valF, 3); + assert(atomic_load_impl(&valF) > 3); } pragma(inline, true) @@ -668,11 +756,15 @@ A atomic_fetch_sub_impl(A, M)(shared(A)* obj, M arg) @trusted } /// -unittest +@trusted unittest { shared(int) val = 3; atomic_fetch_sub_impl(&val, 3); assert(atomic_load_impl(&val) == 0); + + shared(float) valF = 3; + atomic_fetch_sub_impl(&valF, 1); + assert(atomic_load_impl(&valF) < 3); } /// @@ -697,11 +789,15 @@ A atomic_fetch_add_explicit_impl(A, M)(shared(A)* obj, M arg, memory_order order } /// -unittest +@trusted unittest { shared(int) val; atomic_fetch_add_explicit_impl(&val, 3, memory_order.memory_order_seq_cst); assert(atomic_load_impl(&val) == 3); + + shared(float) valF = 3; + atomic_fetch_add_explicit_impl(&valF, 3, memory_order.memory_order_seq_cst); + assert(atomic_load_impl(&valF) > 3); } /// @@ -726,11 +822,15 @@ A atomic_fetch_sub_explicit_impl(A, M)(shared(A)* obj, M arg, memory_order order } /// -unittest +@trusted unittest { shared(int) val = 3; atomic_fetch_sub_explicit_impl(&val, 3, memory_order.memory_order_seq_cst); assert(atomic_load_impl(&val) == 0); + + shared(float) valF = 4; + atomic_fetch_sub_explicit_impl(&valF, 3, memory_order.memory_order_seq_cst); + assert(atomic_load_impl(&valF) < 4); } /// @@ -742,7 +842,7 @@ A atomic_fetch_or_impl(A, M)(shared(A)* obj, M arg) @trusted } /// -unittest +@trusted unittest { shared(int) val = 5; atomic_fetch_or_impl(&val, 3); @@ -771,7 +871,7 @@ A atomic_fetch_or_explicit_impl(A, M)(shared(A)* obj, M arg, memory_order order) } /// -unittest +@trusted unittest { shared(int) val = 5; atomic_fetch_or_explicit_impl(&val, 3, memory_order.memory_order_seq_cst); @@ -787,7 +887,7 @@ A atomic_fetch_xor_impl(A, M)(shared(A)* obj, M arg) @trusted } /// -unittest +@trusted unittest { shared(int) val = 5; atomic_fetch_xor_impl(&val, 3); @@ -816,7 +916,7 @@ A atomic_fetch_xor_explicit_impl(A, M)(shared(A)* obj, M arg, memory_order order } /// -unittest +@trusted unittest { shared(int) val = 5; atomic_fetch_xor_explicit_impl(&val, 3, memory_order.memory_order_seq_cst); @@ -832,7 +932,7 @@ A atomic_fetch_and_impl(A, M)(shared(A)* obj, M arg) @trusted } /// -unittest +@trusted unittest { shared(int) val = 5; atomic_fetch_and_impl(&val, 3); @@ -873,8 +973,9 @@ private: pragma(inline, true) A atomic_fetch_op(memory_order order, string op, A, M)(A* obj, M arg) @trusted { - static if (op == "+=" || op == "-=") + static if (is(A : ulong) && (op == "+=" || op == "-=")) { + // these cannot handle floats static if (op == "+=") { return atomicFetchAdd!order(obj, arg); From b06beb049a106253380f08ef882c36a571730d86 Mon Sep 17 00:00:00 2001 From: Martin Kinkelin Date: Fri, 19 Jan 2024 02:29:18 +0100 Subject: [PATCH 192/215] Handle invalid orderings for fence intrinsic By not emitting any IR instruction, like clang. --- gen/tocall.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/gen/tocall.cpp b/gen/tocall.cpp index 12f03d2bc9f..bbe7d373b67 100644 --- a/gen/tocall.cpp +++ b/gen/tocall.cpp @@ -382,7 +382,12 @@ bool DtoLowerMagicIntrinsic(IRState *p, FuncDeclaration *fndecl, CallExp *e, if (e->arguments->length == 2) { scope = static_cast((*e->arguments)[1]->toInteger()); } - p->ir->CreateFence(atomicOrdering, scope); + // orderings below acquire are invalid; like clang, don't emit any + // instruction in those cases + if (static_cast(atomicOrdering) > + static_cast(llvm::AtomicOrdering::Monotonic)) { + p->ir->CreateFence(atomicOrdering, scope); + } return true; } From 0b0844d75d2084f901f49e9cbc640e29f73e7582 Mon Sep 17 00:00:00 2001 From: Martin Kinkelin Date: Fri, 19 Jan 2024 03:56:27 +0100 Subject: [PATCH 193/215] druntime: Restore LDC-specific macOS extras for test/exceptions/Makefile --- runtime/druntime/test/exceptions/Makefile | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/runtime/druntime/test/exceptions/Makefile b/runtime/druntime/test/exceptions/Makefile index fd975327d9b..12b2abde41b 100644 --- a/runtime/druntime/test/exceptions/Makefile +++ b/runtime/druntime/test/exceptions/Makefile @@ -20,7 +20,9 @@ ifeq ($(OS)-$(BUILD),dragonflybsd-debug) LINE_TRACE_DFLAGS:=-L--export-dynamic endif ifeq ($(OS)-$(BUILD),osx-debug) - TESTS+=line_trace line_trace_21656 long_backtrace_trunc cpp_demangle + # LDC: exclude long_backtrace_trunc, as resolving file:line infos via external `atos` tool + # yields absolute paths of varying lengths + TESTS+=line_trace line_trace_21656 $(if $(findstring ldmd2,$(DMD)),,long_backtrace_trunc) cpp_demangle LINE_TRACE_DFLAGS:= endif ifeq ($(OS)-$(BUILD),windows-debug) @@ -35,6 +37,13 @@ DIFF:=diff SED:=sed GDB:=gdb +ifneq (,$(findstring ldmd2,$(DMD))) + ifeq ($(OS),osx) + # convert absolute paths from `atos` tool to expected relative ones + OSX_SED_MAKE_RELATIVE:=s|^.*/src/|src/|g; + endif +endif + .PHONY: all clean all: $(addprefix $(ROOT)/,$(addsuffix .done,$(TESTS))) @@ -42,7 +51,7 @@ $(ROOT)/line_trace.done: $(ROOT)/line_trace$(DOTEXE) @echo Testing line_trace $(QUIET)$(TIMELIMIT)$(ROOT)/line_trace $(RUN_ARGS) > $(ROOT)/line_trace.output # Use sed to canonicalize line_trace.output and compare against expected output in line_trace.exp - $(QUIET)$(SED) "s/\[0x[0-9a-f]*\]/\[ADDR\]/g; s/scope //g; s/Nl//g" $(ROOT)/line_trace.output | $(DIFF) line_trace.exp - + $(QUIET)$(SED) "$(OSX_SED_MAKE_RELATIVE)s/\[0x[0-9a-f]*\]/\[ADDR\]/g; s/scope //g; s/Nl//g" $(ROOT)/line_trace.output | $(DIFF) line_trace.exp - @rm -f $(ROOT)/line_trace.output @touch $@ @@ -52,7 +61,7 @@ $(ROOT)/line_trace_21656.done: $(ROOT)/line_trace$(DOTEXE) @mkdir -p $(ROOT)/line_trace_21656 @touch $(ROOT)/line_trace_21656/line_trace $(QUIET)cd $(ROOT)/line_trace_21656 && PATH="..:$$PATH" $(TIMELIMIT)line_trace $(RUN_ARGS) > line_trace.output - $(QUIET)$(SED) "s/\[0x[0-9a-f]*\]/\[ADDR\]/g; s/scope //g; s/Nl//g" $(ROOT)/line_trace_21656/line_trace.output | $(DIFF) line_trace.exp - + $(QUIET)$(SED) "$(OSX_SED_MAKE_RELATIVE)s/\[0x[0-9a-f]*\]/\[ADDR\]/g; s/scope //g; s/Nl//g" $(ROOT)/line_trace_21656/line_trace.output | $(DIFF) line_trace.exp - @rm -rf $(ROOT)/line_trace_21656 @touch $@ @@ -60,7 +69,7 @@ $(ROOT)/long_backtrace_trunc.done: $(ROOT)/long_backtrace_trunc$(DOTEXE) @echo Testing long_backtrace_trunc $(QUIET)$(TIMELIMIT)$(ROOT)/long_backtrace_trunc $(RUN_ARGS) > $(ROOT)/long_backtrace_trunc.output # Use sed to canonicalize long_backtrace_trunc.output and compare against expected output in long_backtrace_trunc.exp - $(QUIET)$(SED) "s/\[0x[0-9a-f]*\]/\[ADDR\]/g; s/scope //g; s/Nl//g" $(ROOT)/long_backtrace_trunc.output | $(DIFF) long_backtrace_trunc.exp - + $(QUIET)$(SED) "$(OSX_SED_MAKE_RELATIVE)s/\[0x[0-9a-f]*\]/\[ADDR\]/g; s/scope //g; s/Nl//g" $(ROOT)/long_backtrace_trunc.output | $(DIFF) long_backtrace_trunc.exp - @rm -f $(ROOT)/long_backtrace_trunc.output @touch $@ From 2b5662f13ff235139d82410c15422e6b0a67b792 Mon Sep 17 00:00:00 2001 From: Martin Kinkelin Date: Fri, 19 Jan 2024 03:57:56 +0100 Subject: [PATCH 194/215] druntime: Disable Win32-specific block of newly tested test/exceptions/src/winstack.d for LDC --- runtime/druntime/test/exceptions/src/winstack.d | 1 + 1 file changed, 1 insertion(+) diff --git a/runtime/druntime/test/exceptions/src/winstack.d b/runtime/druntime/test/exceptions/src/winstack.d index 0577a2d04a4..aca7ce469a9 100644 --- a/runtime/druntime/test/exceptions/src/winstack.d +++ b/runtime/druntime/test/exceptions/src/winstack.d @@ -21,6 +21,7 @@ void main() assert(checkStack(ex), "Bad stack"); } + version(LDC) { /* access violations not wrapped as D errors */ } else version(Win32) { // Cannot catch exceptions on Win64 because From 8c99f6a3ee28a41c7fcf4d0bf497be38e9b19d0a Mon Sep 17 00:00:00 2001 From: Martin Kinkelin Date: Fri, 19 Jan 2024 19:14:00 +0100 Subject: [PATCH 195/215] Adapt lit-test codegen/linker_directives_linux.d to -ignore defaulting to true DMD enforces it; we can still NOT ignore unsupported pragmas via `-ignore=false`. --- driver/cl_options.cpp | 2 +- tests/codegen/linker_directives_linux.d | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/driver/cl_options.cpp b/driver/cl_options.cpp index 10549a4004c..81a9f975279 100644 --- a/driver/cl_options.cpp +++ b/driver/cl_options.cpp @@ -179,7 +179,7 @@ static cl::opt warnings( cl::init(DIAGNOSTICoff)); static cl::opt ignoreUnsupportedPragmas( - "ignore", cl::desc("Ignore unsupported pragmas"), cl::ZeroOrMore, + "ignore", cl::desc("Ignore unsupported pragmas (default)"), cl::ZeroOrMore, cl::location(global.params.ignoreUnsupportedPragmas)); static cl::opt cplusplus( diff --git a/tests/codegen/linker_directives_linux.d b/tests/codegen/linker_directives_linux.d index 4701d815920..a1a06ce4e45 100644 --- a/tests/codegen/linker_directives_linux.d +++ b/tests/codegen/linker_directives_linux.d @@ -1,5 +1,5 @@ -// RUN: not %ldc -mtriple=x86_64-linux-gnu -o- %s -// RUN: %ldc -mtriple=x86_64-linux-gnu -ignore -output-ll -of=%t.ll %s && FileCheck %s < %t.ll +// RUN: not %ldc -ignore=false -mtriple=x86_64-linux-gnu -o- %s +// RUN: %ldc -mtriple=x86_64-linux-gnu -output-ll -of=%t.ll %s && FileCheck %s < %t.ll // REQUIRES: target_X86 From a3aadfcce8354ba6752718aabe32fbff3f36f495 Mon Sep 17 00:00:00 2001 From: Martin Kinkelin Date: Fri, 19 Jan 2024 19:42:13 +0100 Subject: [PATCH 196/215] Adapt to new multi-dimensional array allocation lowering Fixes runnable/test28.d. --- gen/arrays.cpp | 68 ------------------------------------------------- gen/arrays.h | 2 -- gen/runtime.cpp | 9 +------ gen/toir.cpp | 10 +++----- 4 files changed, 4 insertions(+), 85 deletions(-) diff --git a/gen/arrays.cpp b/gen/arrays.cpp index 96058ea3ef1..90b149819de 100644 --- a/gen/arrays.cpp +++ b/gen/arrays.cpp @@ -679,74 +679,6 @@ DSliceValue *DtoNewDynArray(const Loc &loc, Type *arrayType, DValue *dim, return new DSliceValue(arrayType, arrayLen, ptr); } -//////////////////////////////////////////////////////////////////////////////// -DSliceValue *DtoNewMulDimDynArray(const Loc &loc, Type *arrayType, - DValue **dims, size_t ndims) { - IF_LOG Logger::println("DtoNewMulDimDynArray : %s", arrayType->toChars()); - LOG_SCOPE; - - // get value type - Type *vtype = arrayType->toBasetype(); - for (size_t i = 0; i < ndims; ++i) { - vtype = vtype->nextOf(); - } - - // get runtime function - const char *fnname = - vtype->isZeroInit() ? "_d_newarraymTX" : "_d_newarraymiTX"; - LLFunction *fn = getRuntimeFunction(loc, gIR->module, fnname); - - // typeinfo arg - LLValue *arrayTypeInfo = DtoTypeInfoOf(loc, arrayType); - - // Check if constant - bool allDimsConst = true; - for (size_t i = 0; i < ndims; ++i) { - if (!isaConstant(DtoRVal(dims[i]))) { - allDimsConst = false; - } - } - - // build dims - LLValue *array; - if (allDimsConst) { - // Build constant array for dimensions - std::vector argsdims; - argsdims.reserve(ndims); - for (size_t i = 0; i < ndims; ++i) { - argsdims.push_back(isaConstant(DtoRVal(dims[i]))); - } - - llvm::Constant *dims = llvm::ConstantArray::get( - llvm::ArrayType::get(DtoSize_t(), ndims), argsdims); - auto gvar = new llvm::GlobalVariable(gIR->module, dims->getType(), true, - LLGlobalValue::InternalLinkage, dims, - ".dimsarray"); - array = llvm::ConstantExpr::getBitCast(gvar, getPtrToType(dims->getType())); - } else { - // Build static array for dimensions - LLArrayType *type = LLArrayType::get(DtoSize_t(), ndims); - array = DtoRawAlloca(type, 0, ".dimarray"); - for (size_t i = 0; i < ndims; ++i) { - DtoStore(DtoRVal(dims[i]), DtoGEP(type, array, 0, i, ".ndim")); - } - } - - LLStructType *dtype = DtoArrayType(DtoSize_t()); - LLValue *darray = DtoRawAlloca(dtype, 0, ".array"); - DtoStore(DtoConstSize_t(ndims), DtoGEP(dtype, darray, 0u, 0, ".len")); - DtoStore(DtoBitCast(array, getPtrToType(DtoSize_t())), - DtoGEP(dtype, darray, 0, 1, ".ptr")); - - // call allocator - LLValue *newptr = - gIR->CreateCallOrInvoke(fn, arrayTypeInfo, DtoLoad(dtype, darray), ".gc_mem"); - - IF_LOG Logger::cout() << "final ptr = " << *newptr << '\n'; - - return getSlice(arrayType, newptr); -} - //////////////////////////////////////////////////////////////////////////////// DSliceValue *DtoAppendDChar(const Loc &loc, DValue *arr, Expression *exp, diff --git a/gen/arrays.h b/gen/arrays.h index 3e893bbdc79..866b6203f99 100644 --- a/gen/arrays.h +++ b/gen/arrays.h @@ -62,8 +62,6 @@ void DtoSetArrayToNull(DValue *v); DSliceValue *DtoNewDynArray(const Loc &loc, Type *arrayType, DValue *dim, bool defaultInit = true); -DSliceValue *DtoNewMulDimDynArray(const Loc &loc, Type *arrayType, - DValue **dims, size_t ndims); DSliceValue *DtoCatArrays(const Loc &loc, Type *type, Expression *e1, Expression *e2); diff --git a/gen/runtime.cpp b/gen/runtime.cpp index 0254f86836f..8bb54510e1d 100644 --- a/gen/runtime.cpp +++ b/gen/runtime.cpp @@ -84,12 +84,10 @@ static void checkForImplicitGCCall(const Loc &loc, const char *name) { "_d_delmemory", "_d_newarrayT", "_d_newarrayiT", - "_d_newarraymTX", - "_d_newarraymiTX", "_d_newarrayU", "_d_newclass", "_d_allocclass", - // TODO: _d_newitemT instantiations + // TODO: _d_newitemT and _d_newarraymTX instantiations }; if (binary_search(&GCNAMES[0], @@ -601,11 +599,6 @@ static void buildRuntimeModule() { {"_d_newarrayT", "_d_newarrayiT", "_d_newarrayU"}, {typeInfoTy, sizeTy}, {STCconst, 0}); - // void[] _d_newarraymTX (const TypeInfo ti, size_t[] dims) - // void[] _d_newarraymiTX(const TypeInfo ti, size_t[] dims) - createFwdDecl(LINK::c, voidArrayTy, {"_d_newarraymTX", "_d_newarraymiTX"}, - {typeInfoTy, sizeTy->arrayOf()}, {STCconst, 0}); - // void[] _d_arrayappendcd(ref byte[] x, dchar c) // void[] _d_arrayappendwd(ref byte[] x, dchar c) createFwdDecl(LINK::c, voidArrayTy, {"_d_arrayappendcd", "_d_arrayappendwd"}, diff --git a/gen/toir.cpp b/gen/toir.cpp index fcc7054c648..4941141302f 100644 --- a/gen/toir.cpp +++ b/gen/toir.cpp @@ -1533,13 +1533,9 @@ class ToElemVisitor : public Visitor { // allocate & init result = DtoNewDynArray(e->loc, e->newtype, sz, true); } else { - size_t ndims = e->arguments->length; - std::vector dims; - dims.reserve(ndims); - for (auto arg : *e->arguments) { - dims.push_back(toElem(arg)); - } - result = DtoNewMulDimDynArray(e->loc, e->newtype, &dims[0], ndims); + assert(e->lowering); + LLValue *pair = DtoRVal(e->lowering); + result = new DSliceValue(e->type, pair); } } // new static array From 61da18939b7ca4cbeee3b80dbf8d940302bee928 Mon Sep 17 00:00:00 2001 From: Martin Kinkelin Date: Sat, 20 Jan 2024 21:02:18 +0100 Subject: [PATCH 197/215] Handle new `@standalone` shared module constructors Fixes runnable/standalone_modctor.d. --- gen/functions.cpp | 21 ++++++++++++--------- gen/moduleinfo.cpp | 39 ++++++++++++++++++++++++++++++--------- ir/irmodule.h | 1 + 3 files changed, 43 insertions(+), 18 deletions(-) diff --git a/gen/functions.cpp b/gen/functions.cpp index 6522a053269..f36befb2f65 100644 --- a/gen/functions.cpp +++ b/gen/functions.cpp @@ -1133,20 +1133,23 @@ void DtoDefineFunction(FuncDeclaration *fd, bool linkageAvailableExternally) { // ignore unparsed unittests from non-root modules if (fd->fbody) getIrModule(gIR->dmodule)->unitTests.push_back(fd); - } else if (fd->isSharedStaticCtorDeclaration()) { - getIrModule(gIR->dmodule)->sharedCtors.push_back(fd); - } else if (StaticDtorDeclaration *dtorDecl = - fd->isSharedStaticDtorDeclaration()) { + } else if (auto sctor = fd->isSharedStaticCtorDeclaration()) { + if (sctor->standalone) { + getIrModule(gIR->dmodule)->standaloneSharedCtors.push_back(fd); + } else { + getIrModule(gIR->dmodule)->sharedCtors.push_back(fd); + } + } else if (auto sdtor = fd->isSharedStaticDtorDeclaration()) { getIrModule(gIR->dmodule)->sharedDtors.push_front(fd); - if (dtorDecl->vgate) { - getIrModule(gIR->dmodule)->sharedGates.push_front(dtorDecl->vgate); + if (sdtor->vgate) { + getIrModule(gIR->dmodule)->sharedGates.push_front(sdtor->vgate); } } else if (fd->isStaticCtorDeclaration()) { getIrModule(gIR->dmodule)->ctors.push_back(fd); - } else if (StaticDtorDeclaration *dtorDecl = fd->isStaticDtorDeclaration()) { + } else if (auto dtor = fd->isStaticDtorDeclaration()) { getIrModule(gIR->dmodule)->dtors.push_front(fd); - if (dtorDecl->vgate) { - getIrModule(gIR->dmodule)->gates.push_front(dtorDecl->vgate); + if (dtor->vgate) { + getIrModule(gIR->dmodule)->gates.push_front(dtor->vgate); } } diff --git a/gen/moduleinfo.cpp b/gen/moduleinfo.cpp index 65e673aae14..c471c3c4608 100644 --- a/gen/moduleinfo.cpp +++ b/gen/moduleinfo.cpp @@ -42,8 +42,8 @@ namespace { /// functions one after each other and then increments the gate variables, if /// any. llvm::Function *buildForwarderFunction( - const std::string &name, const std::list &funcs, - const std::list &gates = std::list()) { + const std::string &name, const std::vector &funcs, + const std::list &gates = {}) { // If there is no gates, we might get away without creating a function at all. if (gates.empty()) { if (funcs.empty()) { @@ -51,7 +51,7 @@ llvm::Function *buildForwarderFunction( } if (funcs.size() == 1) { - return DtoCallee(funcs.front()); + return funcs.front(); } } @@ -77,10 +77,9 @@ llvm::Function *buildForwarderFunction( } // ... calling the given functions, and... - for (auto func : funcs) { - const auto f = DtoCallee(func); + for (auto f : funcs) { const auto call = builder.CreateCall(f, {}); - call->setCallingConv(gABI->callingConv(func)); + call->setCallingConv(f->getCallingConv()); } // ... incrementing the gate variables. @@ -97,7 +96,19 @@ llvm::Function *buildForwarderFunction( return fn; } -namespace { +std::vector toLLVMFuncs(const std::list &funcs) { + std::vector ret; + for (auto func : funcs) + ret.push_back(DtoCallee(func)); + return ret; +} + +llvm::Function *buildForwarderFunction( + const std::string &name, const std::list &funcs, + const std::list &gates = {}) { + return buildForwarderFunction(name, toLLVMFuncs(funcs), gates); +} + std::string getMangledName(Module *m, const char *suffix) { OutBuffer buf; buf.writestring("_D"); @@ -106,7 +117,6 @@ std::string getMangledName(Module *m, const char *suffix) { buf.writestring(suffix); return buf.peekChars(); } -} llvm::Function *buildModuleCtor(Module *m) { std::string name = getMangledName(m, "6__ctorZ"); @@ -135,6 +145,17 @@ llvm::Function *buildModuleSharedDtor(Module *m) { return buildForwarderFunction(name, getIrModule(m)->sharedDtors); } +llvm::Function *buildOrderIndependentModuleCtor(Module *m) { + std::string name = getMangledName(m, "7__ictorZ"); + IrModule &irm = *getIrModule(m); + + auto funcs = toLLVMFuncs(irm.standaloneSharedCtors); + if (irm.coverageCtor) + funcs.insert(funcs.begin(), irm.coverageCtor); // initialize coverage first + + return buildForwarderFunction(name, funcs); +} + /// Builds the (constant) data content for the importedModules[] array. llvm::Constant *buildImportedModules(Module *m, size_t &count) { const auto moduleInfoPtrTy = DtoPtrToType(getModuleInfoType()); @@ -238,7 +259,7 @@ llvm::GlobalVariable *genModuleInfo(Module *m) { flags |= MIxgetMembers; #endif - const auto fictor = getIrModule(m)->coverageCtor; + const auto fictor = buildOrderIndependentModuleCtor(m); if (fictor) flags |= MIictor; diff --git a/ir/irmodule.h b/ir/irmodule.h index 7905ff98b67..c596619f0a8 100644 --- a/ir/irmodule.h +++ b/ir/irmodule.h @@ -38,6 +38,7 @@ struct IrModule { FuncDeclList ctors; FuncDeclList dtors; FuncDeclList sharedCtors; + FuncDeclList standaloneSharedCtors; FuncDeclList sharedDtors; GatesList gates; GatesList sharedGates; From 32f78fa5561d202f8191960793e3ea1fb4be7707 Mon Sep 17 00:00:00 2001 From: Martin Kinkelin Date: Sat, 20 Jan 2024 21:23:01 +0100 Subject: [PATCH 198/215] druntime: Add __nan and __builtin_nanf symbols to importC builtins, like DMD MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Looks totally arbitrary (single precision only…), but oh well, this makes compilable/stdcheaders.c happy. --- runtime/druntime/src/__builtins.di | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/runtime/druntime/src/__builtins.di b/runtime/druntime/src/__builtins.di index a96e4b09fcf..03d166fba43 100644 --- a/runtime/druntime/src/__builtins.di +++ b/runtime/druntime/src/__builtins.di @@ -138,6 +138,10 @@ version (DigitalMars) } else version (LDC) { + immutable float __nan = float.nan; + + float __builtin_nanf()(char*) { return float.nan; } + double __builtin_inf()() { return double.infinity; } float __builtin_inff()() { return float.infinity; } real __builtin_infl()() { return real.infinity; } From 8baab34dd2e7210a374f46b2819bc66d78f5362b Mon Sep 17 00:00:00 2001 From: Martin Kinkelin Date: Sat, 20 Jan 2024 21:28:45 +0100 Subject: [PATCH 199/215] Minimally adapt new runnable/gdb22905.d to support gdb-demangled backtraces --- tests/dmd/runnable/gdb22905.d | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/dmd/runnable/gdb22905.d b/tests/dmd/runnable/gdb22905.d index 842f61414b1..7551fdb769a 100644 --- a/tests/dmd/runnable/gdb22905.d +++ b/tests/dmd/runnable/gdb22905.d @@ -10,7 +10,7 @@ cont end run --- -GDB_MATCH: _D7imports9gdb22905b5funcBFZv .. at runnable/imports/gdb22905b.d:7 +GDB_MATCH: (_D7imports9gdb22905b5funcBFZv|imports\.gdb22905b\.funcB\(\)) .. at runnable/imports/gdb22905b.d:7 */ import imports.gdb22905b; From a87be8111bea3dc1fab3d97fefbf3a5ccfe449f7 Mon Sep 17 00:00:00 2001 From: Iain Buclaw Date: Sun, 21 Jan 2024 00:54:56 +0100 Subject: [PATCH 200/215] core.stdc.stdatomic: Do nothing for atomic fence with relaxed memory orders --- runtime/druntime/src/core/stdc/stdatomic.d | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/runtime/druntime/src/core/stdc/stdatomic.d b/runtime/druntime/src/core/stdc/stdatomic.d index b2736bc4d39..7f62a776343 100644 --- a/runtime/druntime/src/core/stdc/stdatomic.d +++ b/runtime/druntime/src/core/stdc/stdatomic.d @@ -273,7 +273,7 @@ void atomic_signal_fence_impl()(memory_order order) final switch (order) { case memory_order.memory_order_relaxed: - atomicSignalFence!(memory_order.memory_order_relaxed); + // This is a no-op operation for relaxed memory orders. break; case memory_order.memory_order_acquire: @@ -307,7 +307,7 @@ void atomic_thread_fence_impl()(memory_order order) final switch (order) { case memory_order.memory_order_relaxed: - atomicFence!(memory_order.memory_order_relaxed); + // This is a no-op operation for relaxed memory orders. break; case memory_order.memory_order_acquire: From a7ed49e8a7519525d63b2a1575f90a8170e8fc02 Mon Sep 17 00:00:00 2001 From: Martin Kinkelin Date: Sun, 21 Jan 2024 12:32:14 +0100 Subject: [PATCH 201/215] ldmd2: Support new upstream options -dllimport and -visibility --- driver/ldmd.cpp | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/driver/ldmd.cpp b/driver/ldmd.cpp index a1f4140eaa1..3b7f08f508f 100644 --- a/driver/ldmd.cpp +++ b/driver/ldmd.cpp @@ -155,8 +155,11 @@ Where:\n\ -conf= use config file at filename\n\ -cov do code coverage analysis\n\ -cov=ctfe include code executed during CTFE in coverage report\n\ - -cov= require at least nnn%% code coverage\n\ - -D generate documentation\n\ + -cov= require at least nnn%% code coverage\n" +#if 0 +" -cpp= use filename as the name of the C preprocessor to use for ImportC files\n" +#endif +" -D generate documentation\n\ -Dd write documentation file to directory\n\ -Df write documentation file to filename\n\ -d silently allow deprecated features and symbols\n\ @@ -170,6 +173,8 @@ Where:\n\ set default library to name\n\ -deps print module dependencies (imports/file/version/debug/lib)\n\ -deps= write module dependencies to filename (only imports)\n\ + -dllimport=\n\ + Windows only: select symbols to dllimport (none/defaultLibsOnly/all)\n\ -extern-std=\n\ set C++ name mangling compatibility with \n" #if 0 @@ -201,7 +206,7 @@ Where:\n\ --help print help and exit\n\ -I= look for imports also in directory\n\ -i[=] include imported modules in the compilation\n\ - -ignore ignore unsupported pragmas\n\ + -ignore deprecated flag, unsupported pragmas are always ignored now\n\ -inline do function inlining\n\ -J= look for string imports also in directory\n\ -L= pass linkerflag to link\n\ @@ -245,7 +250,7 @@ Where:\n\ #if 0 " -profile=gc profile runtime allocations\n" #endif -" -release compile release version\n\ +" -release contracts and asserts are not emitted, and bounds checking is performed only in @safe functions\n\ -revert= revert language change identified by 'name'\n\ -revert=[h|help|?]\n\ list all revertable language changes\n\ @@ -272,12 +277,13 @@ Where:\n\ -version= compile in version code >= level\n\ -version= compile in version code identified by ident\n\ -vgc list all gc allocations including hidden ones\n\ + -visibility=\n\ + default visibility of symbols (default/hidden/public)\n\ -vtemplates=[list-instances]\n\ list statistics on template instantiations\n\ -vtls list all variables going into thread local storage\n\ -w warnings as errors (compilation will halt)\n\ -wi warnings as messages (compilation will continue)\n\ - -wo warnings about use of obsolete features (compilation will continue)\n\ -X generate JSON file\n\ -Xf= write JSON file to filename\n\ -Xcc= pass driverflag to linker driver (cc)\n", @@ -491,6 +497,11 @@ void translateArgs(const llvm::SmallVectorImpl &ldmdArgs, * -cov * -shared */ + else if (startsWith(p + 1, "visibility=")) { + ldcArgs.push_back(concat("-fvisibility=", p + 12)); + } + /* -dllimport + */ else if (strcmp(p + 1, "dylib") == 0) { ldcArgs.push_back("-shared"); } else if (strcmp(p + 1, "fIBT") == 0) { From 86d267c35eab16bd2bbff929bdeee550c5ea4b3b Mon Sep 17 00:00:00 2001 From: Martin Kinkelin Date: Sun, 21 Jan 2024 13:14:14 +0100 Subject: [PATCH 202/215] core.stdc.stdatomic: Treat all non-DMD compilers as 'C-compatible', not just GDC --- runtime/druntime/src/core/stdc/stdatomic.d | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/runtime/druntime/src/core/stdc/stdatomic.d b/runtime/druntime/src/core/stdc/stdatomic.d index 7f62a776343..ab73a7e476b 100644 --- a/runtime/druntime/src/core/stdc/stdatomic.d +++ b/runtime/druntime/src/core/stdc/stdatomic.d @@ -103,7 +103,7 @@ version (DigitalMars) alias atomic_fetch_and_explicit = atomic_fetch_and_explicit_impl; /// } } -else version(GNU) +else { alias atomic_flag_clear = atomic_flag_clear_impl; /// alias atomic_flag_clear_explicit = atomic_flag_clear_explicit_impl; /// From 2cb84e20673ddbffa34d4c9eaa4c76d1f0f80d6e Mon Sep 17 00:00:00 2001 From: Martin Kinkelin Date: Sun, 21 Jan 2024 16:34:45 +0100 Subject: [PATCH 203/215] core.stdc.stdatomic: Align shared locals of double-word size in unittests --- runtime/druntime/src/core/stdc/stdatomic.d | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/runtime/druntime/src/core/stdc/stdatomic.d b/runtime/druntime/src/core/stdc/stdatomic.d index 7f62a776343..c9575261453 100644 --- a/runtime/druntime/src/core/stdc/stdatomic.d +++ b/runtime/druntime/src/core/stdc/stdatomic.d @@ -490,7 +490,7 @@ A atomic_load_impl(A)(const shared(A)* obj) @trusted { size_t[2] values; } - shared(S2) objS2 = {[1, 2]}; + align(S2.sizeof) shared(S2) objS2 = {[1, 2]}; assert(atomic_load_impl(&objS2).values == [1, 2]); } @@ -666,7 +666,7 @@ bool atomic_compare_exchange_strong_explicit_impl(A, B, C)(shared(A)* obj, B* ex /// @trusted unittest { - shared(size_t[2]) obj = [3, 4]; + align(size_t[2].sizeof) shared(size_t[2]) obj = [3, 4]; size_t[2] expected = [3, 4]; size_t[2] toSwap = [1, 2]; assert(atomic_compare_exchange_strong_explicit_impl(&obj, &expected, toSwap, memory_order.memory_order_seq_cst, memory_order.memory_order_seq_cst)); @@ -714,7 +714,7 @@ bool atomic_compare_exchange_weak_explicit_impl(A, B, C)(shared(A)* obj, B* expe /// @trusted unittest { - shared(size_t[2]) obj = [3, 4]; + align(size_t[2].sizeof) shared(size_t[2]) obj = [3, 4]; size_t[2] expected = [3, 4]; size_t[2] toSwap = [1, 2]; assert(atomic_compare_exchange_weak_explicit_impl(&obj, &expected, toSwap, memory_order.memory_order_seq_cst, memory_order.memory_order_seq_cst)); From 1ee602bb2383ad60e243115c34da0f3e3180ba16 Mon Sep 17 00:00:00 2001 From: Martin Kinkelin Date: Sun, 21 Jan 2024 18:21:42 +0100 Subject: [PATCH 204/215] Minimally adapt new runnable/gdb22905.d to support gdb-demangled backtraces (dlang/dmd!16069) --- tests/dmd/runnable/gdb22905.d | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/dmd/runnable/gdb22905.d b/tests/dmd/runnable/gdb22905.d index 842f61414b1..7551fdb769a 100644 --- a/tests/dmd/runnable/gdb22905.d +++ b/tests/dmd/runnable/gdb22905.d @@ -10,7 +10,7 @@ cont end run --- -GDB_MATCH: _D7imports9gdb22905b5funcBFZv .. at runnable/imports/gdb22905b.d:7 +GDB_MATCH: (_D7imports9gdb22905b5funcBFZv|imports\.gdb22905b\.funcB\(\)) .. at runnable/imports/gdb22905b.d:7 */ import imports.gdb22905b; From f2ad949311ab5a49a661892d16a05781858295a2 Mon Sep 17 00:00:00 2001 From: Iain Buclaw Date: Mon, 22 Jan 2024 01:22:36 +0100 Subject: [PATCH 205/215] core.internal.atomic: Fix atomicLoad for N sized atomic types (dlang/dmd!16073) Unlike all other fallback paths to libatomic in this module, `atomicLoad` was missing a cast to `void*`. --- runtime/druntime/src/core/internal/atomic.d | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/runtime/druntime/src/core/internal/atomic.d b/runtime/druntime/src/core/internal/atomic.d index b864357d977..6e51f8ef410 100644 --- a/runtime/druntime/src/core/internal/atomic.d +++ b/runtime/druntime/src/core/internal/atomic.d @@ -642,7 +642,7 @@ else version (GNU) else static if (GNU_Have_LibAtomic) { T value; - __atomic_load(T.sizeof, cast(shared)src, &value, order); + __atomic_load(T.sizeof, cast(shared)src, cast(void*)&value, order); return *cast(typeof(return)*)&value; } else From 6c62113f53918e2a1daab1f8dfcae6d789db2e3d Mon Sep 17 00:00:00 2001 From: Martin Kinkelin Date: Mon, 22 Jan 2024 12:33:58 +0100 Subject: [PATCH 206/215] core.stdc.stdatomic: Align double-word locals in unittests --- runtime/druntime/src/core/stdc/stdatomic.d | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/runtime/druntime/src/core/stdc/stdatomic.d b/runtime/druntime/src/core/stdc/stdatomic.d index ab73a7e476b..72e037f7e92 100644 --- a/runtime/druntime/src/core/stdc/stdatomic.d +++ b/runtime/druntime/src/core/stdc/stdatomic.d @@ -490,7 +490,7 @@ A atomic_load_impl(A)(const shared(A)* obj) @trusted { size_t[2] values; } - shared(S2) objS2 = {[1, 2]}; + align(S2.sizeof) shared(S2) objS2 = {[1, 2]}; assert(atomic_load_impl(&objS2).values == [1, 2]); } @@ -666,7 +666,7 @@ bool atomic_compare_exchange_strong_explicit_impl(A, B, C)(shared(A)* obj, B* ex /// @trusted unittest { - shared(size_t[2]) obj = [3, 4]; + align(size_t[2].sizeof) shared(size_t[2]) obj = [3, 4]; size_t[2] expected = [3, 4]; size_t[2] toSwap = [1, 2]; assert(atomic_compare_exchange_strong_explicit_impl(&obj, &expected, toSwap, memory_order.memory_order_seq_cst, memory_order.memory_order_seq_cst)); @@ -714,7 +714,7 @@ bool atomic_compare_exchange_weak_explicit_impl(A, B, C)(shared(A)* obj, B* expe /// @trusted unittest { - shared(size_t[2]) obj = [3, 4]; + align(size_t[2].sizeof) shared(size_t[2]) obj = [3, 4]; size_t[2] expected = [3, 4]; size_t[2] toSwap = [1, 2]; assert(atomic_compare_exchange_weak_explicit_impl(&obj, &expected, toSwap, memory_order.memory_order_seq_cst, memory_order.memory_order_seq_cst)); From e35731486d295e039f20e7219c0019be5e8e9ebe Mon Sep 17 00:00:00 2001 From: Martin Kinkelin Date: Sat, 27 Jan 2024 15:11:03 +0100 Subject: [PATCH 207/215] Fix Bugzilla Issue 24252 - Object files collision for tests compilable/testcstuff3.{d,i} --- tests/dmd/compilable/{testcstuff3.i => testcstuff4.i} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename tests/dmd/compilable/{testcstuff3.i => testcstuff4.i} (100%) diff --git a/tests/dmd/compilable/testcstuff3.i b/tests/dmd/compilable/testcstuff4.i similarity index 100% rename from tests/dmd/compilable/testcstuff3.i rename to tests/dmd/compilable/testcstuff4.i From 890a57c0f23707da46fb3cb7e3c9d6c60baa9de2 Mon Sep 17 00:00:00 2001 From: Martin Kinkelin Date: Wed, 31 Jan 2024 20:56:39 +0100 Subject: [PATCH 208/215] Adapt LDC-specifics to d_do_test.d changes --- tests/dmd/runnable/test17559.d | 2 +- tests/dmd/tools/d_do_test.d | 6 ------ 2 files changed, 1 insertion(+), 7 deletions(-) diff --git a/tests/dmd/runnable/test17559.d b/tests/dmd/runnable/test17559.d index e22a396f0eb..822ef940248 100644 --- a/tests/dmd/runnable/test17559.d +++ b/tests/dmd/runnable/test17559.d @@ -1,6 +1,6 @@ // REQUIRED_ARGS: -g // REQUIRED_ARGS(linux freebsd dragonflybsd): -L-export-dynamic -// LDC (required for Win32 and -O): REQUIRED_ARGS(windows32): -link-defaultlib-debug +// LDC (required for Win32 and -O): REQUIRED_ARGS(windows32mscoff): -link-defaultlib-debug // LDC (FreeBSD's libexecinfo apparently doesn't like elided frame pointers): REQUIRED_ARGS(freebsd): -link-defaultlib-debug -frame-pointer=all // PERMUTE_ARGS: // DISABLED: osx diff --git a/tests/dmd/tools/d_do_test.d b/tests/dmd/tools/d_do_test.d index 864300542f2..9249b0c86f2 100755 --- a/tests/dmd/tools/d_do_test.d +++ b/tests/dmd/tools/d_do_test.d @@ -198,8 +198,6 @@ immutable(EnvData) processEnvironment() { if (envData.os != "windows") envData.ccompiler = "c++"; - else version (LDC_MSVC) - envData.ccompiler = "cl.exe"; else if (envData.model == "32omf") envData.ccompiler = "dmc"; else if (envData.model == "64") @@ -645,10 +643,6 @@ string getDisabledReason(string[] disabledPlatforms, const ref EnvData envData) const j = disabledPlatforms.countUntil!(p => p.startsWith("LDC_") && target.canFind(p[4 .. $])); if (j != -1) return "for LDC on " ~ disabledPlatforms[j]; - - // we don't use the 32mscoff model, but 32 instead - if (target == "win32" && disabledPlatforms.canFind("win32mscoff")) - return "on win32mscoff"; } return null; From fe1380370da97dcb823deb58b90f5ff225e91c07 Mon Sep 17 00:00:00 2001 From: Martin Kinkelin Date: Wed, 31 Jan 2024 22:02:41 +0100 Subject: [PATCH 209/215] Add changelog entry --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6fc133ccac6..3d071189468 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,7 @@ # LDC master #### Big news +- Frontend, druntime and Phobos are at version [2.107.0](https://dlang.org/changelog/2.107.0.html). (#4563) #### Platform support From 0aadc977ac2074cbf04e9998cbdbef2f6de22126 Mon Sep 17 00:00:00 2001 From: Martin Kinkelin Date: Wed, 31 Jan 2024 22:03:33 +0100 Subject: [PATCH 210/215] Bump Phobos submodule --- runtime/phobos | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/runtime/phobos b/runtime/phobos index 622c15577e4..cf121699120 160000 --- a/runtime/phobos +++ b/runtime/phobos @@ -1 +1 @@ -Subproject commit 622c15577e4011754ca7072ec2a3a95f6d3a8136 +Subproject commit cf12169912096c14209ddb1bc1524447f085a53b From 89a0d110210f66ac4625f7e632b0a9391d75a986 Mon Sep 17 00:00:00 2001 From: Razvan Nitu Date: Fri, 2 Feb 2024 02:06:03 +0200 Subject: [PATCH 211/215] Fix Bugzilla 24365 - ICE when printing showCtfeContext error (dlang/dmd!16131) --- dmd/dsymbolsem.d | 3 ++- tests/dmd/fail_compilation/test24365.d | 20 ++++++++++++++++++++ 2 files changed, 22 insertions(+), 1 deletion(-) create mode 100644 tests/dmd/fail_compilation/test24365.d diff --git a/dmd/dsymbolsem.d b/dmd/dsymbolsem.d index 61190109eb6..c92ea9b3c7b 100644 --- a/dmd/dsymbolsem.d +++ b/dmd/dsymbolsem.d @@ -1343,9 +1343,10 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor dsym._init = dsym._init.initializerSemantic(sc, dsym.type, sc.intypeof == 1 ? INITnointerpret : INITinterpret); import dmd.semantic2 : lowerStaticAAs; lowerStaticAAs(dsym, sc); - const init_err = dsym._init.isExpInitializer(); + auto init_err = dsym._init.isExpInitializer(); if (init_err && init_err.exp.op == EXP.showCtfeContext) { + init_err.exp = ErrorExp.get(); errorSupplemental(dsym.loc, "compile time context created here"); } } diff --git a/tests/dmd/fail_compilation/test24365.d b/tests/dmd/fail_compilation/test24365.d new file mode 100644 index 00000000000..9ec1e2ac3a9 --- /dev/null +++ b/tests/dmd/fail_compilation/test24365.d @@ -0,0 +1,20 @@ +// https://issues.dlang.org/show_bug.cgi?id=243645 + +/* +TEST_OUTPUT: +--- +fail_compilation/test24365.d(16): Error: `f` cannot be interpreted at compile time, because it has no available source code +fail_compilation/test24365.d(14): compile time context created here +fail_compilation/test24365.d(19): while evaluating: `static assert(r == 2)` +--- +*/ + +void main() +{ + enum r = () { + void f(); + f(); + return 2; + }(); + static assert(r == 2); +} From 22e601e467a43a35bbb3a095b6e20713a0519e86 Mon Sep 17 00:00:00 2001 From: Martin Kinkelin Date: Sat, 3 Feb 2024 15:13:16 +0100 Subject: [PATCH 212/215] Bump Phobos and bundled dlang tools / dub / reggae --- packaging/dlang-tools_version | 2 +- packaging/dub_version | 2 +- packaging/reggae_version | 2 +- runtime/phobos | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/packaging/dlang-tools_version b/packaging/dlang-tools_version index ff7708cd44a..114c98e5e81 100644 --- a/packaging/dlang-tools_version +++ b/packaging/dlang-tools_version @@ -1 +1 @@ -v2.106.1 \ No newline at end of file +v2.107.0 \ No newline at end of file diff --git a/packaging/dub_version b/packaging/dub_version index 5f241b4eeb7..3c9507effd6 100644 --- a/packaging/dub_version +++ b/packaging/dub_version @@ -1 +1 @@ -v1.35.1 \ No newline at end of file +v1.36.0 \ No newline at end of file diff --git a/packaging/reggae_version b/packaging/reggae_version index 5f1b4513e3b..ab1254dd709 100644 --- a/packaging/reggae_version +++ b/packaging/reggae_version @@ -1 +1 @@ -b9e70e1b2f24e897c532da0515d55f137bba798a \ No newline at end of file +82aeeac43381fc98e0a57ef1bd5907211f596172 \ No newline at end of file diff --git a/runtime/phobos b/runtime/phobos index cf121699120..2154018026a 160000 --- a/runtime/phobos +++ b/runtime/phobos @@ -1 +1 @@ -Subproject commit cf12169912096c14209ddb1bc1524447f085a53b +Subproject commit 2154018026aa2d2664b08807c754695eb6b9587a From dc110f6fd0f6ecb90e10e786aa523f804afa619a Mon Sep 17 00:00:00 2001 From: Martin Kinkelin Date: Wed, 24 Jan 2024 19:32:02 +0100 Subject: [PATCH 213/215] CI: Fix reggae build regressions (now uses rdmd in preGenerateCommand) --- .cirrus.yml | 3 ++- .github/actions/7-package/action.yml | 4 ++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/.cirrus.yml b/.cirrus.yml index 5887ddf975c..8314f860a7a 100644 --- a/.cirrus.yml +++ b/.cirrus.yml @@ -143,7 +143,8 @@ packaging_steps_template: &PACKAGING_STEPS_TEMPLATE git clone --recursive https://github.com/atilaneves/reggae.git cd reggae git checkout "$(cat $CIRRUS_WORKING_DIR/packaging/reggae_version)" - DFLAGS="-O -linkonce-templates" ../dub/bin/dub build -v --combined --compiler="$PWD/../installed/bin/ldc2" + # needs rdmd in PATH + PATH="$PWD/../installed/bin:$PATH" DFLAGS="-O -linkonce-templates" ../dub/bin/dub build -v --build-mode=allAtOnce --combined --compiler="$PWD/../installed/bin/ldc2" cp bin/reggae ../installed/bin ../installed/bin/reggae --version -b ninja # Pack artifact diff --git a/.github/actions/7-package/action.yml b/.github/actions/7-package/action.yml index b98e31e04bc..e2d1e109cb7 100644 --- a/.github/actions/7-package/action.yml +++ b/.github/actions/7-package/action.yml @@ -67,6 +67,10 @@ runs: archFlag='' if [[ '${{ inputs.cross_target_triple }}' != '' ]]; then archFlag='--arch=${{ inputs.cross_target_triple }}' + + # run the preGenerateCommand manually; it must be a native build + sed -i${{ runner.os == 'macOS' && ' ""' || '' }} 's|^ "preGenerateCommands": \["rdmd \$PACKAGE_DIR/list_payload.d \$PACKAGE_DIR"\],$||' dub.json + "$(dirname "$DMD")/ldc2" -run list_payload.d . fi # use host compiler's dub, which is guaranteed to be native From deeaced0fe4d15b86b25aaaae1b464e2c7f6eefa Mon Sep 17 00:00:00 2001 From: Martin Kinkelin Date: Sat, 3 Feb 2024 19:39:07 +0100 Subject: [PATCH 214/215] druntime: Slightly revise LDC-specifics in core.internal.atomic --- runtime/druntime/src/core/internal/atomic.d | 33 +++++++++++++-------- 1 file changed, 21 insertions(+), 12 deletions(-) diff --git a/runtime/druntime/src/core/internal/atomic.d b/runtime/druntime/src/core/internal/atomic.d index e5073b6ab7b..8cf8002fe55 100644 --- a/runtime/druntime/src/core/internal/atomic.d +++ b/runtime/druntime/src/core/internal/atomic.d @@ -18,10 +18,13 @@ version (LDC) pragma(inline, true): - enum IsAtomicLockFree(T) = T.sizeof <= 8 || (T.sizeof <= 16 && has128BitCAS); + enum IsAtomicLockFree(T) = is(_AtomicType!T); inout(T) atomicLoad(MemoryOrder order = MemoryOrder.seq, T)(inout(T)* src) pure nothrow @nogc @trusted { + static assert(order != MemoryOrder.rel && order != MemoryOrder.acq_rel, + "invalid MemoryOrder for atomicLoad()"); + alias A = _AtomicType!T; A result = llvm_atomic_load!A(cast(shared A*) src, _ordering!(order)); return *cast(inout(T)*) &result; @@ -29,17 +32,22 @@ version (LDC) void atomicStore(MemoryOrder order = MemoryOrder.seq, T)(T* dest, T value) pure nothrow @nogc @trusted { + static assert(order != MemoryOrder.acq && order != MemoryOrder.acq_rel, + "Invalid MemoryOrder for atomicStore()"); + alias A = _AtomicType!T; llvm_atomic_store!A(*cast(A*) &value, cast(shared A*) dest, _ordering!(order)); } T atomicFetchAdd(MemoryOrder order = MemoryOrder.seq, T)(T* dest, T value) pure nothrow @nogc @trusted + if (is(T : ulong)) { alias A = _AtomicType!T; return llvm_atomic_rmw_add!A(cast(shared A*) dest, value, _ordering!(order)); } T atomicFetchSub(MemoryOrder order = MemoryOrder.seq, T)(T* dest, T value) pure nothrow @nogc @trusted + if (is(T : ulong)) { alias A = _AtomicType!T; return llvm_atomic_rmw_sub!A(cast(shared A*) dest, value, _ordering!(order)); @@ -47,6 +55,8 @@ version (LDC) T atomicExchange(MemoryOrder order = MemoryOrder.seq, bool result = true, T)(T* dest, T value) pure nothrow @nogc @trusted { + static assert(order != MemoryOrder.acq, "Invalid MemoryOrder for atomicExchange()"); + alias A = _AtomicType!T; A result = llvm_atomic_rmw_xchg!A(cast(shared A*) dest, *cast(A*) &value, _ordering!(order)); return *cast(T*) &result; @@ -54,6 +64,10 @@ version (LDC) bool atomicCompareExchange(bool weak = false, MemoryOrder succ = MemoryOrder.seq, MemoryOrder fail = MemoryOrder.seq, T)(T* dest, T* compare, T value) pure nothrow @nogc @trusted { + static assert(fail != MemoryOrder.rel && fail != MemoryOrder.acq_rel, + "Invalid fail MemoryOrder for atomicCompareExchange()"); + static assert (succ >= fail, "The first MemoryOrder argument for atomicCompareExchange() cannot be weaker than the second argument"); + alias A = _AtomicType!T; auto result = llvm_atomic_cmp_xchg!A(cast(shared A*) dest, *cast(A*) compare, *cast(A*) &value, _ordering!(succ), _ordering!(fail), weak); @@ -71,6 +85,10 @@ version (LDC) bool atomicCompareExchangeNoResult(bool weak = false, MemoryOrder succ = MemoryOrder.seq, MemoryOrder fail = MemoryOrder.seq, T)(T* dest, const T compare, T value) pure nothrow @nogc @trusted { + static assert(fail != MemoryOrder.rel && fail != MemoryOrder.acq_rel, + "Invalid fail MemoryOrder for atomicCompareExchange()"); + static assert (succ >= fail, "The first MemoryOrder argument for atomicCompareExchange() cannot be weaker than the second argument"); + alias A = _AtomicType!T; auto result = llvm_atomic_cmp_xchg!A(cast(shared A*) dest, *cast(A*) &compare, *cast(A*) &value, _ordering!(succ), _ordering!(fail), weak); @@ -165,18 +183,9 @@ version (LDC) else static if (T.sizeof == ulong.sizeof) alias _AtomicType = ulong; else static if (T.sizeof == 2*ulong.sizeof && has128BitCAS) - { - struct UCent - { - ulong value1; - ulong value2; - } - - alias _AtomicType = UCent; - } + alias _AtomicType = imported!"core.int128".Cent; else - static assert(is(_AtomicType!T), - "Cannot atomically load/store type of size " ~ T.sizeof.stringof); + static assert(false, "Cannot atomically load/store type of size " ~ T.sizeof.stringof); } } else: // !LDC From 3cb389ae084da59b6d42928435667b37d286ec0b Mon Sep 17 00:00:00 2001 From: Martin Kinkelin Date: Mon, 5 Feb 2024 15:18:45 +0100 Subject: [PATCH 215/215] Bump bundled reggae to latest master Which uses latest dub v1.36. --- packaging/reggae_version | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packaging/reggae_version b/packaging/reggae_version index ab1254dd709..95ada7c7968 100644 --- a/packaging/reggae_version +++ b/packaging/reggae_version @@ -1 +1 @@ -82aeeac43381fc98e0a57ef1bd5907211f596172 \ No newline at end of file +8995c511f1484022ce2927964bdf65190e0c672b \ No newline at end of file