diff options
author | Iain Buclaw <ibuclaw@gdcproject.org> | 2025-03-14 01:36:45 +0100 |
---|---|---|
committer | Iain Buclaw <ibuclaw@gdcproject.org> | 2025-03-16 20:49:55 +0100 |
commit | 26c4ea2ebcdcd0aa26350d04dc4cd38348148bd9 (patch) | |
tree | abe80e8d65acfee1b474c17cdbbb6c04894cac96 /gcc/d/dmd | |
parent | 427972b2f1335c7430785ad4afd15386a17156ec (diff) | |
download | gcc-26c4ea2ebcdcd0aa26350d04dc4cd38348148bd9.zip gcc-26c4ea2ebcdcd0aa26350d04dc4cd38348148bd9.tar.gz gcc-26c4ea2ebcdcd0aa26350d04dc4cd38348148bd9.tar.bz2 |
d: Merge upstream dmd, druntime 53a1cc8d13
D front-end changes:
- Typesafe variadic class parameters have been deprecated.
D runtime changes:
- Added `entry' field to TypeInfo_AssociativeArray.
gcc/d/ChangeLog:
* dmd/MERGE: Merge upstream dmd 53a1cc8d13.
* d-tree.h (create_typeinfo): Change second parameter to Scope *.
(speculative_type_p): Remove prototype.
* d-frontend.cc (getTypeInfoType): Adjust.
* decl.cc: Include dmd/typinf.h.
(DeclVisitor::visit (TypeInfoDeclaration *)): Update for new front-end
interface.
* typeinfo.cc (create_typeinfo): Likewise.
(class SpeculativeTypeVisitor): Remove class.
(speculative_type_p): Remove function.
libphobos/ChangeLog:
* libdruntime/MERGE: Merge upstream druntime 53a1cc8d13.
gcc/testsuite/ChangeLog:
* gdc.dg/pr100967.d: Adjust error message.
Diffstat (limited to 'gcc/d/dmd')
40 files changed, 643 insertions, 337 deletions
diff --git a/gcc/d/dmd/MERGE b/gcc/d/dmd/MERGE index 59d5a18..66cfdd6 100644 --- a/gcc/d/dmd/MERGE +++ b/gcc/d/dmd/MERGE @@ -1,4 +1,4 @@ -ffbad272b649b7ae3e88cfdc85688bfef3168994 +53a1cc8d13e8db2cb1642219320a8dfc1b0cc6c5 The first line of this file holds the git revision number of the last merge done from the dlang/dmd repository. diff --git a/gcc/d/dmd/attrib.d b/gcc/d/dmd/attrib.d index f5618f1..df04ed1 100644 --- a/gcc/d/dmd/attrib.d +++ b/gcc/d/dmd/attrib.d @@ -32,7 +32,7 @@ import dmd.declaration; import dmd.dmodule; import dmd.dscope; import dmd.dsymbol; -import dmd.dsymbolsem : setScope, addMember, include; +import dmd.dsymbolsem : include; import dmd.expression; import dmd.func; import dmd.globals; @@ -125,11 +125,6 @@ extern (C++) abstract class AttribDeclaration : Dsymbol return this.include(null).foreachDsymbol( (s) { return s.hasStaticCtorOrDtor(); } ) != 0; } - override final void checkCtorConstInit() - { - this.include(null).foreachDsymbol( s => s.checkCtorConstInit() ); - } - /**************************************** */ override final void addObjcSymbols(ClassDeclarations* classes, ClassDeclarations* categories) diff --git a/gcc/d/dmd/attrib.h b/gcc/d/dmd/attrib.h index 79b0cb0..ab5f219 100644 --- a/gcc/d/dmd/attrib.h +++ b/gcc/d/dmd/attrib.h @@ -32,7 +32,6 @@ public: bool oneMember(Dsymbol *&ps, Identifier *ident) override; bool hasPointers() override final; bool hasStaticCtorOrDtor() override final; - void checkCtorConstInit() override final; AttribDeclaration *isAttribDeclaration() override { return this; } void accept(Visitor *v) override { v->visit(this); } diff --git a/gcc/d/dmd/common/charactertables.d b/gcc/d/dmd/common/charactertables.d index ac89807..6a3b302 100644 --- a/gcc/d/dmd/common/charactertables.d +++ b/gcc/d/dmd/common/charactertables.d @@ -42,7 +42,8 @@ struct IdentifierCharLookup // Awful solution to require these lambdas. // However without them the extern(C++) ABI issues crop up for isInRange, // and then it can't access the tables. - final switch(table) { + final switch(table) + { case IdentifierTable.UAX31: return IdentifierCharLookup( (c) => isInRange!UAX31_Start(c), diff --git a/gcc/d/dmd/cparse.d b/gcc/d/dmd/cparse.d index 548bee9..9f1eab7 100644 --- a/gcc/d/dmd/cparse.d +++ b/gcc/d/dmd/cparse.d @@ -2006,7 +2006,7 @@ final class CParser(AST) : Parser!AST //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 + ad.hidden = true; // do not print when generating .di files s = ad; } @@ -2088,8 +2088,7 @@ final class CParser(AST) : Parser!AST { auto str = asmName.peekString(); p.mangleOverride = str; -// p.adFlags |= AST.VarDeclaration.nounderscore; - p.adFlags |= 4; // cannot get above line to compile on Ubuntu + p.noUnderscore = true; } } s = applySpecifier(s, specifier); @@ -5527,6 +5526,12 @@ final class CParser(AST) : Parser!AST if (pt && *pt) t = *pt; } + if (t.mcache && t.mcache.typedefIdent) + { + t = t.copy(); + t.mcache = null; + } + t.getMcache().typedefIdent = id; auto tab = cast(void*[void*])(typedefTab[$ - 1]); tab[cast(void*)id] = cast(void*)t; typedefTab[$ - 1] = cast(void*)tab; diff --git a/gcc/d/dmd/cxxfrontend.d b/gcc/d/dmd/cxxfrontend.d index dfc76ff..3cd4ced 100644 --- a/gcc/d/dmd/cxxfrontend.d +++ b/gcc/d/dmd/cxxfrontend.d @@ -15,6 +15,7 @@ import dmd.arraytypes; import dmd.astenums; import dmd.attrib; import dmd.common.outbuffer : OutBuffer; +import dmd.declaration : TypeInfoDeclaration; import dmd.denum : EnumDeclaration; import dmd.dmodule /*: Module*/; import dmd.dscope : Scope; @@ -702,6 +703,18 @@ bool builtinTypeInfo(Type t) return dmd.typinf.builtinTypeInfo(t); } +Type makeNakedAssociativeArray(TypeAArray t) +{ + import dmd.typinf; + return dmd.typinf.makeNakedAssociativeArray(t); +} + +TypeInfoDeclaration getTypeInfoAssocArrayDeclaration(TypeAArray t, Scope* sc) +{ + import dmd.typinf; + return dmd.typinf.getTypeInfoAssocArrayDeclaration(t, sc); +} + version (IN_LLVM) { /*********************************************************** diff --git a/gcc/d/dmd/dcast.d b/gcc/d/dmd/dcast.d index f42a061..172c827 100644 --- a/gcc/d/dmd/dcast.d +++ b/gcc/d/dmd/dcast.d @@ -150,7 +150,7 @@ Expression implicitCastTo(Expression e, Scope* sc, Type t) //printf("type %s t %s\n", type.deco, t.deco); auto ts = toAutoQualChars(e.type, t); error(e.loc, "cannot implicitly convert expression `%s` of type `%s` to `%s`", - e.toChars(), ts[0], ts[1]); + e.toErrMsg(), ts[0], ts[1]); } } return ErrorExp.get(); @@ -2832,6 +2832,7 @@ Expression castTo(Expression e, Scope* sc, Type t, Type att = null) (*ae.keys)[i] = ex; } ae.type = t; + semanticTypeInfo(sc, ae.type); return ae; } return visit(e); diff --git a/gcc/d/dmd/declaration.d b/gcc/d/dmd/declaration.d index 26887f8..30f017d 100644 --- a/gcc/d/dmd/declaration.d +++ b/gcc/d/dmd/declaration.d @@ -54,6 +54,7 @@ else version = MARS; */ void ObjectNotFound(Loc loc, Identifier id) { + global.gag = 0; // never gag the fatal error error(loc, "`%s` not found. object.d may be incorrectly installed or corrupt.", id.toChars()); version (IN_LLVM) { @@ -87,19 +88,23 @@ extern (C++) abstract class Declaration : Dsymbol Type type; Type originalType; // before semantic analysis StorageClass storage_class = STC.undefined_; + // overridden symbol with pragma(mangle, "...") + const(char)[] mangleOverride; Visibility visibility; - LINK _linkage = LINK.default_; // may be `LINK.system`; use `resolvedLinkage()` to resolve it short inuse; // used to detect cycles - ubyte adFlags; // control re-assignment of AliasDeclaration (put here for packing reasons) - enum wasRead = 1; // set if AliasDeclaration was read - enum ignoreRead = 2; // ignore any reads of AliasDeclaration - enum nounderscore = 4; // don't prepend _ to mangled name - enum hidden = 8; // don't print this in .di files - enum nrvo = 0x10; /// forward to fd.nrvo_var when generating code + private extern (D) static struct BitFields + { + LINK _linkage = LINK.default_; // may be `LINK.system`; use `resolvedLinkage()` to resolve it + bool wasRead; // set if AliasDeclaration was read + bool ignoreRead; // ignore any reads of AliasDeclaration + bool noUnderscore; // don't prepend _ to mangled name + bool hidden; // don't print this in .di files + bool nrvo; /// forward to fd.nrvo_var when generating code + } - // overridden symbol with pragma(mangle, "...") - const(char)[] mangleOverride; + import dmd.common.bitfields; + mixin(generateBitFields!(BitFields, ubyte)); final extern (D) this(Identifier ident) @safe { @@ -628,8 +633,8 @@ extern (C++) final class AliasDeclaration : Declaration return aliassym; } // Reading the AliasDeclaration - if (!(adFlags & ignoreRead)) - adFlags |= wasRead; // can never assign to this AliasDeclaration again + if (!this.ignoreRead) + this.wasRead = true; // can never assign to this AliasDeclaration again if (inuse == 1 && type && _scope) { @@ -1124,16 +1129,6 @@ extern (C++) class VarDeclaration : Declaration return e; } - override final void checkCtorConstInit() - { - version (none) - { - /* doesn't work if more than one static ctor */ - if (ctorinit == 0 && isCtorinit() && !isField()) - error("missing initializer in static constructor for const variable"); - } - } - /************************************ * Check to see if this variable is actually in an enclosing function * rather than the current one. @@ -1544,6 +1539,8 @@ extern (C++) final class TypeInfoStaticArrayDeclaration : TypeInfoDeclaration */ extern (C++) final class TypeInfoAssociativeArrayDeclaration : TypeInfoDeclaration { + Type entry; // type of TypeInfo_AssociativeArray.Entry!(t.index, t.next) + extern (D) this(Type tinfo) { super(tinfo); diff --git a/gcc/d/dmd/declaration.h b/gcc/d/dmd/declaration.h index 4fd35ee..6fef6a5 100644 --- a/gcc/d/dmd/declaration.h +++ b/gcc/d/dmd/declaration.h @@ -121,11 +121,10 @@ public: Type *type; Type *originalType; // before semantic analysis StorageClass storage_class; + DString mangleOverride; // overridden symbol with pragma(mangle, "...") Visibility visibility; - LINK _linkage; // may be `LINK::system`; use `resolvedLinkage()` to resolve it short inuse; // used to detect cycles - uint8_t adFlags; - DString mangleOverride; // overridden symbol with pragma(mangle, "...") + uint8_t bitFields; const char *kind() const override; uinteger_t size(Loc loc) override final; @@ -299,7 +298,6 @@ public: bool hasPointers() override final; bool canTakeAddressOf(); bool needsScopeDtor(); - void checkCtorConstInit() override final; Dsymbol *toAlias() override final; // Eliminate need for dynamic_cast VarDeclaration *isVarDeclaration() override final { return (VarDeclaration *)this; } @@ -398,6 +396,8 @@ public: class TypeInfoAssociativeArrayDeclaration final : public TypeInfoDeclaration { public: + Type* entry; + static TypeInfoAssociativeArrayDeclaration *create(Type *tinfo); void accept(Visitor *v) override { v->visit(this); } diff --git a/gcc/d/dmd/dinterpret.d b/gcc/d/dmd/dinterpret.d index 5dbab09..3a08c10 100644 --- a/gcc/d/dmd/dinterpret.d +++ b/gcc/d/dmd/dinterpret.d @@ -1989,13 +1989,15 @@ public: Declaration decl = ve.var; // We cannot take the address of an imported symbol at compile time - if (decl.isImportedSymbol()) { + if (decl.isImportedSymbol()) + { error(e.loc, "cannot take address of imported symbol `%s` at compile time", decl.toChars()); result = CTFEExp.cantexp; return; } - if (decl.isDataseg()) { + if (decl.isDataseg()) + { // Normally this is already done by optimize() // Do it here in case optimize(WANTvalue) wasn't run before CTFE emplaceExp!(SymOffExp)(pue, e.loc, e.e1.isVarExp().var, 0); diff --git a/gcc/d/dmd/doc.d b/gcc/d/dmd/doc.d index 0e77cdf..261fa38 100644 --- a/gcc/d/dmd/doc.d +++ b/gcc/d/dmd/doc.d @@ -2061,9 +2061,9 @@ string toLowercase(string s) pure @safe // TODO: maybe unicode lowercase, somehow if (c >= 'A' && c <= 'Z') { - if (!lower.length) { + if (!lower.length) lower.reserve(s.length); - } + lower ~= s[lower.length..i]; c += 'a' - 'A'; lower ~= c; diff --git a/gcc/d/dmd/dsymbol.d b/gcc/d/dmd/dsymbol.d index bad9ca2..64cf6be 100644 --- a/gcc/d/dmd/dsymbol.d +++ b/gcc/d/dmd/dsymbol.d @@ -916,10 +916,6 @@ extern (C++) class Dsymbol : ASTNode { } - void checkCtorConstInit() - { - } - /**************************************** * Add documentation comment to Dsymbol. * Ignore NULL comments. diff --git a/gcc/d/dmd/dsymbol.h b/gcc/d/dmd/dsymbol.h index 6d223bf..8209dea 100644 --- a/gcc/d/dmd/dsymbol.h +++ b/gcc/d/dmd/dsymbol.h @@ -241,7 +241,6 @@ public: virtual bool hasPointers(); virtual bool hasStaticCtorOrDtor(); virtual void addObjcSymbols(ClassDeclarations *, ClassDeclarations *) { } - virtual void checkCtorConstInit() { } virtual void addComment(const utf8_t *comment); const utf8_t *comment(); // current value of comment diff --git a/gcc/d/dmd/dsymbolsem.d b/gcc/d/dmd/dsymbolsem.d index 3e7f9b9..b017366 100644 --- a/gcc/d/dmd/dsymbolsem.d +++ b/gcc/d/dmd/dsymbolsem.d @@ -1896,8 +1896,7 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor const sident = se.toStringz(); if (!sident.length || !Identifier.isValidIdentifier(sident)) { - error(ns.exp.loc, "expected valid identifier for C++ namespace but got `%.*s`", - cast(int)sident.length, sident.ptr); + error(ns.exp.loc, "expected valid identifier for C++ namespace but got `%s`", se.toErrMsg()); return null; } else @@ -5343,7 +5342,8 @@ void aliasSemantic(AliasDeclaration ds, Scope* sc) { s = tident.toDsymbol(sc); // don't error for `var1.static_symbol` - if (s && s.needThis()) { + if (s && s.needThis()) + { error(ds.loc, "cannot alias %s member `%s` of variable `%s`", s.kind(), s.toChars(), mt.ident.toChars()); errorSupplemental(ds.loc, "Use `typeof(%s)` instead to preserve behaviour", @@ -5500,7 +5500,7 @@ private void aliasAssignSemantic(AliasAssign ds, Scope* sc) if (!aliassym) return errorRet(); - if (aliassym.adFlags & Declaration.wasRead) + if (aliassym.wasRead) { if (!aliassym.errors) error(ds.loc, "%s was read, so cannot reassign", aliassym.toChars()); @@ -5508,7 +5508,7 @@ private void aliasAssignSemantic(AliasAssign ds, Scope* sc) return errorRet(); } - aliassym.adFlags |= Declaration.ignoreRead; // temporarilly allow reads of aliassym + aliassym.ignoreRead = true; // temporarilly allow reads of aliassym const storage_class = sc.stc & (STC.deprecated_ | STC.ref_ | STC.nothrow_ | STC.nogc | STC.pure_ | STC.shared_ | STC.disable); @@ -5632,8 +5632,7 @@ private void aliasAssignSemantic(AliasAssign ds, Scope* sc) aliassym.aliassym = null; } - - aliassym.adFlags &= ~Declaration.ignoreRead; + aliassym.ignoreRead = false; if (aliassym.type && aliassym.type.ty == Terror || global.gag && errors != global.errors) @@ -7940,3 +7939,31 @@ extern (C++) class AddCommentVisitor: Visitor } override void visit(StaticForeachDeclaration sfd) {} } + +void checkCtorConstInit(Dsymbol d) +{ + scope v = new CheckCtorConstInitVisitor(); + d.accept(v); +} + +private extern(C++) class CheckCtorConstInitVisitor : Visitor +{ + alias visit = Visitor.visit; + + override void visit(AttribDeclaration ad) + { + ad.include(null).foreachDsymbol( s => s.checkCtorConstInit() ); + } + + override void visit(VarDeclaration vd) + { + version (none) + { + /* doesn't work if more than one static ctor */ + if (vd.ctorinit == 0 && vd.isCtorinit() && !vd.isField()) + error("missing initializer in static constructor for const variable"); + } + } + + override void visit(Dsymbol d){} +} diff --git a/gcc/d/dmd/dtemplate.d b/gcc/d/dmd/dtemplate.d index 1aab94d..c19d4b9 100644 --- a/gcc/d/dmd/dtemplate.d +++ b/gcc/d/dmd/dtemplate.d @@ -136,6 +136,13 @@ inout(Parameter) isParameter(inout RootObject o) return cast(inout(Parameter))o; } +inout(Identifier) isIdentifier(inout RootObject o) +{ + if (!o || o.dyncast() != DYNCAST.identifier) + return null; + return cast(inout(Identifier))o; +} + inout(TemplateParameter) isTemplateParameter(inout RootObject o) { if (!o || o.dyncast() != DYNCAST.templateparameter) @@ -3884,7 +3891,7 @@ extern (C++) class TemplateInstance : ScopeDsymbol if (n_instantiations <= max_shown) { for (TemplateInstance cur = this; cur; cur = cur.tinst) - printFn(cur.loc, format, cur.toChars()); + printFn(cur.loc, format, cur.toErrMsg()); } else if (n_instantiations - n_totalrecursions <= max_shown) { @@ -6265,6 +6272,9 @@ void write(ref OutBuffer buf, RootObject obj) { if (obj) { - buf.writestring(obj.toChars()); + if (auto e = isExpression(obj)) + buf.writestring(e.toErrMsg()); + else + buf.writestring(obj.toChars()); } } diff --git a/gcc/d/dmd/dtoh.d b/gcc/d/dmd/dtoh.d index efd0a2f..a586f87 100644 --- a/gcc/d/dmd/dtoh.d +++ b/gcc/d/dmd/dtoh.d @@ -976,7 +976,8 @@ public: { EnumKind kind = getEnumKind(type); - if (vd.visibility.kind == AST.Visibility.Kind.none || vd.visibility.kind == AST.Visibility.Kind.private_) { + if (vd.visibility.kind == AST.Visibility.Kind.none || vd.visibility.kind == AST.Visibility.Kind.private_) + { ignored("enum `%s` because it is `%s`.", vd.toPrettyChars(), AST.visibilityToChars(vd.visibility.kind)); return; } diff --git a/gcc/d/dmd/expression.d b/gcc/d/dmd/expression.d index 6827612..388023f 100644 --- a/gcc/d/dmd/expression.d +++ b/gcc/d/dmd/expression.d @@ -383,8 +383,7 @@ extern (C++) abstract class Expression : ASTNode final override const(char)* toChars() const { - // FIXME: Test suite relies on lambda's being printed as __lambdaXXX in errors and .stringof - // Printing a (truncated) lambda body is more user friendly + // FIXME: mangling (see runnable/mangle.d) relies on toChars outputting __lambdaXXX here if (auto fe = isFuncExp()) return fe.fd.toChars(); diff --git a/gcc/d/dmd/expressionsem.d b/gcc/d/dmd/expressionsem.d index 7a35328..22fbfc2 100644 --- a/gcc/d/dmd/expressionsem.d +++ b/gcc/d/dmd/expressionsem.d @@ -362,11 +362,11 @@ private Expression incompatibleTypes(UnaExp e) if (e.e1.op == EXP.type) { - error(e.loc, "incompatible type for `%s(%s)`: cannot use `%s` with types", EXPtoString(e.op).ptr, e.e1.toChars(), EXPtoString(e.op).ptr); + error(e.loc, "incompatible type for `%s(%s)`: cannot use `%s` with types", EXPtoString(e.op).ptr, e.e1.toErrMsg(), EXPtoString(e.op).ptr); } else { - error(e.loc, "incompatible type for `%s(%s)`: `%s`", EXPtoString(e.op).ptr, e.e1.toChars(), e.e1.type.toChars()); + error(e.loc, "incompatible type for `%s(%s)`: `%s`", EXPtoString(e.op).ptr, e.e1.toErrMsg(), e.e1.type.toChars()); } return ErrorExp.get(); } @@ -393,18 +393,18 @@ extern (D) Expression incompatibleTypes(BinExp e, Scope* sc = null) if (e.e1.op == EXP.type || e.e2.op == EXP.type) { error(e.loc, "incompatible types for `(%s) %s (%s)`: cannot use `%s` with types", - e.e1.toChars(), thisOp, e.e2.toChars(), EXPtoString(e.op).ptr); + e.e1.toErrMsg(), thisOp, e.e2.toErrMsg(), EXPtoString(e.op).ptr); } else if (e.e1.type.equals(e.e2.type)) { error(e.loc, "incompatible types for `(%s) %s (%s)`: both operands are of type `%s`", - e.e1.toChars(), thisOp, e.e2.toChars(), e.e1.type.toChars()); + e.e1.toErrMsg(), thisOp, e.e2.toErrMsg(), e.e1.type.toChars()); } else { auto ts = toAutoQualChars(e.e1.type, e.e2.type); error(e.loc, "incompatible types for `(%s) %s (%s)`: `%s` and `%s`", - e.e1.toChars(), thisOp, e.e2.toChars(), ts[0], ts[1]); + e.e1.toErrMsg(), thisOp, e.e2.toErrMsg(), ts[0], ts[1]); } return ErrorExp.get(); } @@ -731,7 +731,7 @@ Expression resolveOpDollar(Scope* sc, ArrayExp ae, out Expression pe0) if (!e.type) { - error(ae.loc, "`%s` has no value", e.toChars()); + error(ae.loc, "`%s` has no value", e.toErrMsg()); e = ErrorExp.get(); } if (e.op == EXP.error) @@ -768,7 +768,7 @@ Expression resolveOpDollar(Scope* sc, ArrayExp ae, IntervalExp ie, ref Expressio e = resolveProperties(sc, e); if (!e.type) { - error(ae.loc, "`%s` has no value", e.toChars()); + error(ae.loc, "`%s` has no value", e.toErrMsg()); errors = true; } return e; @@ -853,7 +853,7 @@ extern (D) Expression doCopyOrMove(Scope* sc, Expression e, Type t, bool nrvo, b */ VarDeclaration vd = new VarDeclaration(e.loc, e.type, Identifier.generateId("__copyrvalue"), null); if (nrvo) - vd.adFlags |= Declaration.nrvo; + vd.nrvo = true; vd.storage_class |= STC.nodtor; vd.dsymbolSemantic(sc); Expression de = new DeclarationExp(e.loc, vd); @@ -903,7 +903,7 @@ private Expression callCpCtor(Scope* sc, Expression e, Type destinationType, boo */ VarDeclaration tmp = copyToTemp(STC.rvalue, "__copytmp", e); if (nrvo) - tmp.adFlags |= Declaration.nrvo; + tmp.nrvo = true; if (sd.hasCopyCtor && destinationType) { // https://issues.dlang.org/show_bug.cgi?id=22619 @@ -2109,7 +2109,7 @@ public void errorSupplementalInferredAttr(FuncDeclaration fd, int maxDepth, bool { if (maxDepth > 0) { - errorFunc(s.loc, "which calls `%s`", s.fd.toPrettyChars()); + errorFunc(s.loc, "which calls `%s`", s.fd.toErrMsg()); errorSupplementalInferredAttr(s.fd, maxDepth - 1, deprecation, stc, eSink); } } @@ -2477,7 +2477,7 @@ private Expression resolvePropertiesX(Scope* sc, Expression e1, Expression e2 = auto tf = fd.type.isTypeFunction(); if (!tf.isRef && e2) { - error(loc, "%s is not an lvalue", e1.toChars()); + error(loc, "%s is not an lvalue", e1.toErrMsg()); return ErrorExp.get(); } } @@ -2645,13 +2645,13 @@ private Expression resolvePropertiesX(Scope* sc, Expression e1, Expression e2 = if (!e1.type) { - error(loc, "cannot resolve type for %s", e1.toChars()); + error(loc, "cannot resolve type for %s", e1.toErrMsg()); e1 = ErrorExp.get(); } return e1; Leprop: - error(loc, "not a property %s", e1.toChars()); + error(loc, "not a property %s", e1.toErrMsg()); return ErrorExp.get(); } @@ -2715,7 +2715,7 @@ private Type arrayExpressionToCommonType(Scope* sc, ref Expressions exps) e = resolveProperties(sc, e); if (!e.type) { - error(e.loc, "`%s` has no value", e.toChars()); + error(e.loc, "`%s` has no value", e.toErrMsg()); t0 = Type.terror; continue; } @@ -2912,7 +2912,7 @@ private bool preFunctionParameters(Scope* sc, ArgumentList argumentList, ErrorSi { if (eSink) { - eSink.error(arg.loc, "cannot pass type `%s` as a function argument", arg.toChars()); + eSink.error(arg.loc, "cannot pass type `%s` as a function argument", arg.toErrMsg()); arg = ErrorExp.get(); } err = true; @@ -2922,7 +2922,7 @@ private bool preFunctionParameters(Scope* sc, ArgumentList argumentList, ErrorSi { if (eSink) { - eSink.error(arg.loc, "cannot pass function `%s` as a function argument", arg.toChars()); + eSink.error(arg.loc, "cannot pass function `%s` as a function argument", arg.toErrMsg()); arg = ErrorExp.get(); } err = true; @@ -3515,7 +3515,7 @@ private bool functionParameters(Loc loc, Scope* sc, { if (se.hasOverloads && !se.var.isFuncDeclaration().isUnique()) { - error(arg.loc, "function `%s` is overloaded", arg.toChars()); + error(arg.loc, "function `%s` is overloaded", arg.toErrMsg()); err = true; } } @@ -4159,7 +4159,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor { if (!s) { - error(e.loc, "`%s` is not in a class or struct scope", e.toChars()); + error(e.loc, "`%s` is not in a class or struct scope", e.toErrMsg()); return setError(); } ClassDeclaration cd = s.isClassDeclaration(); @@ -4225,7 +4225,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor { if (!s) { - error(e.loc, "`%s` is not in a class scope", e.toChars()); + error(e.loc, "`%s` is not in a class scope", e.toErrMsg()); return setError(); } cd = s.isClassDeclaration(); @@ -4489,7 +4489,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor e = e.expressionSemantic(sc); if (!e.type) { - error(exp.loc, "`%s` has no value", e.toChars()); + error(exp.loc, "`%s` has no value", e.toErrMsg()); err = true; } else if (e.op == EXP.error) @@ -4540,7 +4540,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor */ if (e.elements.length > 0 && t0.ty == Tvoid) { - error(e.loc, "`%s` of type `%s` has no value", e.toChars(), e.type.toChars()); + error(e.loc, "`%s` of type `%s` has no value", e.toErrMsg(), e.type.toChars()); return setError(); } @@ -4864,14 +4864,6 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor id = new DotTemplateInstanceExp(ne.loc, id, 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(ne.loc, ne.loc.filename.toDString())); - arguments.push(new IntegerExp(ne.loc, ne.loc.linnum, Type.tint32)); - arguments.push(new StringExp(ne.loc, funcname.toDString())); - } id = new CallExp(ne.loc, id, arguments); ne.lowering = id.expressionSemantic(sc); @@ -5210,14 +5202,6 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor tiargs.push(t); id = new DotTemplateInstanceExp(exp.loc, id, 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())); - } id = new CallExp(exp.loc, id, arguments); exp.lowering = id.expressionSemantic(sc); @@ -5359,9 +5343,9 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor 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()); + error(exp.loc, "expression `%s` allocates with the GC and cannot be used with switch `-fno-rtti`", exp.toErrMsg()); else - error(exp.loc, "expression `%s` allocates with the GC and cannot be used with switch `-betterC`", exp.toChars()); + error(exp.loc, "expression `%s` allocates with the GC and cannot be used with switch `-betterC`", exp.toErrMsg()); return setError(); } @@ -5402,14 +5386,6 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor 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((*exp.arguments)[0]); arguments.push(new IntegerExp(exp.loc, isShared, Type.tbool)); @@ -5441,14 +5417,6 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor 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)); @@ -5832,8 +5800,8 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor OutBuffer buf; foreach (idx, ref arg; *arguments) buf.printf("%s%s", (idx ? ", ".ptr : "".ptr), arg.type.toChars()); - error(exp.loc, "function literal `%s%s` is not callable using argument types `(%s)`", - exp.fd.toChars(), parametersTypeToChars(tfl.parameterList), + error(exp.loc, "`%s` is not callable using argument types `(%s)`", + exp.fd.toErrMsg(), // parametersTypeToChars(tfl.parameterList), buf.peekChars()); errorSupplemental(exp.loc, "too %s arguments, expected %d, got %d", arguments.length < dim ? "few".ptr : "many".ptr, @@ -6038,7 +6006,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor __gshared int nest; if (++nest > global.recursionLimit) { - error(exp.loc, "recursive evaluation of `%s`", exp.toChars()); + error(exp.loc, "recursive evaluation of `%s`", exp.toErrMsg()); --nest; return setError(); } @@ -6331,7 +6299,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor return null; if (f) return f; - .error(loc, "no overload matches for `%s`", exp.toChars()); + .error(loc, "no overload matches for `%s`", exp.toErrMsg()); errorSupplemental(loc, "Candidates are:"); foreach (s; os.a) { @@ -6591,7 +6559,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor } else if (!t1) { - error(exp.loc, "function expected before `()`, not `%s`", exp.e1.toChars()); + error(exp.loc, "function expected before `()`, not `%s`", exp.e1.toErrMsg()); return setError(); } else if (t1.ty == Terror) @@ -6674,7 +6642,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor } else { - error(exp.loc, "function expected before `()`, not `%s` of type `%s`", exp.e1.toChars(), exp.e1.type.toChars()); + error(exp.loc, "function expected before `()`, not `%s` of type `%s`", exp.e1.toErrMsg(), exp.e1.type.toChars()); return setError(); } @@ -6688,8 +6656,8 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor tthis.modToBuffer(buf); //printf("tf = %s, args = %s\n", tf.deco, (*arguments)[0].type.deco); - .error(exp.loc, "%s `%s%s` is not callable using argument types `%s`", - p, exp.e1.toChars(), parametersTypeToChars(tf.parameterList), buf.peekChars()); + .error(exp.loc, "%s `%s` is not callable using argument types `%s`", + p, exp.e1.toErrMsg(), buf.peekChars()); if (failMessage) errorSupplemental(exp.loc, "%s", failMessage); } @@ -6712,20 +6680,20 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor if (!tf.purity && sc.func.setImpure(exp.loc, "calling impure `%s`", exp.e1)) { error(exp.loc, "`pure` %s `%s` cannot call impure %s `%s`", - sc.func.kind(), sc.func.toPrettyChars(), p, exp.e1.toChars()); + sc.func.kind(), sc.func.toPrettyChars(), p, exp.e1.toErrMsg()); err = true; } if (!tf.isNogc && sc.func.setGC(exp.loc, "calling non-@nogc `%s`", exp.e1)) { error(exp.loc, "`@nogc` %s `%s` cannot call non-@nogc %s `%s`", - sc.func.kind(), sc.func.toPrettyChars(), p, exp.e1.toChars()); + sc.func.kind(), sc.func.toPrettyChars(), p, exp.e1.toErrMsg()); err = true; } if (tf.trust <= TRUST.system && sc.setUnsafe(true, exp.loc, "calling `@system` `%s`", exp.e1)) { error(exp.loc, "`@safe` %s `%s` cannot call `@system` %s `%s`", - sc.func.kind(), sc.func.toPrettyChars(), p, exp.e1.toChars()); + sc.func.kind(), sc.func.toPrettyChars(), p, exp.e1.toErrMsg()); err = true; } if (err) @@ -6770,7 +6738,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor } .error(exp.loc, "%s `%s` is not callable using argument types `%s`", - exp.f.kind(), exp.f.toChars(), buf.peekChars()); + exp.f.kind(), exp.f.toErrMsg(), buf.peekChars()); if (failMessage) errorSupplemental(exp.loc, "%s", failMessage); .errorSupplemental(exp.f.loc, "`%s%s` declared here", exp.f.toPrettyChars(), parametersTypeToChars(tf.parameterList)); @@ -6846,7 +6814,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor { exp.e1 = e1org; // https://issues.dlang.org/show_bug.cgi?id=10922 // avoid recursive expression printing - error(exp.loc, "forward reference to inferred return type of function call `%s`", exp.toChars()); + error(exp.loc, "forward reference to inferred return type of function call `%s`", exp.toErrMsg()); return setError(); } @@ -7126,7 +7094,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor if (!ta) { //printf("ta %p ea %p sa %p\n", ta, ea, sa); - error(exp.loc, "no type for `typeid(%s)`", ea ? ea.toChars() : (sa ? sa.toChars() : "")); + error(exp.loc, "no type for `typeid(%s)`", ea ? ea.toErrMsg() : (sa ? sa.toChars() : "")); return setError(); } @@ -7798,7 +7766,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor // 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()); + e.toErrMsg()); } const generateMsg = !exp.msg && @@ -8430,7 +8398,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor MODMatchToBuffer(&thisBuf, e.e1.type.mod, tf.mod); MODMatchToBuffer(&funcBuf, tf.mod, e.e1.type.mod); error(e.loc, "%smethod `%s` is not callable using a %s`%s`", - funcBuf.peekChars(), f.toPrettyChars(), thisBuf.peekChars(), e.e1.toChars()); + funcBuf.peekChars(), f.toPrettyChars(), thisBuf.peekChars(), e.e1.toErrMsg()); return setError(); } } @@ -8614,7 +8582,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor if (!exp.e1.type) { - error(exp.loc, "cannot take address of `%s`", exp.e1.toChars()); + error(exp.loc, "cannot take address of `%s`", exp.e1.toErrMsg()); return setError(); } if (!checkAddressable(exp, sc)) @@ -8638,7 +8606,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor error(exp.loc, "forward reference to %s `%s`", d.kind(), d.toChars()); } else - error(exp.loc, "forward reference to type `%s` of expression `%s`", exp.e1.type.toChars(), exp.e1.toChars()); + error(exp.loc, "forward reference to type `%s` of expression `%s`", exp.e1.type.toChars(), exp.e1.toErrMsg()); return setError(); } } @@ -8801,7 +8769,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor case Tarray: if (isNonAssignmentArrayOp(exp.e1)) goto default; - error(exp.loc, "using `*` on an array is no longer supported; use `*(%s).ptr` instead", exp.e1.toChars()); + error(exp.loc, "using `*` on an array is no longer supported; use `*(%s).ptr` instead", exp.e1.toErrMsg()); exp.type = (cast(TypeArray)tb).next; exp.e1 = exp.e1.castTo(sc, exp.type.pointerTo()); break; @@ -9111,7 +9079,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor if (!exp.e1.type) { - error(exp.loc, "cannot cast `%s`", exp.e1.toChars()); + error(exp.loc, "cannot cast `%s`", exp.e1.toErrMsg()); return setError(); } @@ -9149,7 +9117,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor if (exp.to.ty == Ttuple) { - error(exp.loc, "cannot cast `%s` of type `%s` to type sequence `%s`", exp.e1.toChars(), exp.e1.type.toChars(), exp.to.toChars()); + error(exp.loc, "cannot cast `%s` of type `%s` to type sequence `%s`", exp.e1.toErrMsg(), exp.e1.type.toChars(), exp.to.toChars()); return setError(); } @@ -9333,7 +9301,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor if (elem.isConst() == 1) return false; - error(exp.loc, "constant expression expected, not `%s`", elem.toChars()); + error(exp.loc, "constant expression expected, not `%s`", elem.toErrMsg()); return true; } @@ -9393,7 +9361,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor { if (exp.lwr || exp.upr) { - error(exp.loc, "cannot slice type `%s`", exp.e1.toChars()); + error(exp.loc, "cannot slice type `%s`", exp.e1.toErrMsg()); return setError(); } Expression e = new TypeExp(exp.loc, exp.e1.type.arrayOf()); @@ -9445,7 +9413,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor { if (t1b.isPtrToFunction()) { - error(exp.loc, "cannot slice function pointer `%s`", exp.e1.toChars()); + error(exp.loc, "cannot slice function pointer `%s`", exp.e1.toErrMsg()); return setError(); } if (!exp.lwr || !exp.upr) @@ -9462,9 +9430,9 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor { errorSupplemental(exp.loc, "pointer `%s` points to an aggregate that defines an `%s`, perhaps you meant `(*%s)[]`", - exp.e1.toChars(), + exp.e1.toErrMsg(), s.ident.toChars(), - exp.e1.toChars() + exp.e1.toErrMsg() ); } @@ -9505,7 +9473,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor } else { - error(exp.loc, "`%s` cannot be sliced with `[]`", t1b.ty == Tvoid ? exp.e1.toChars() : t1b.toChars()); + error(exp.loc, "`%s` cannot be sliced with `[]`", t1b.ty == Tvoid ? exp.e1.toErrMsg() : t1b.toChars()); return setError(); } @@ -9981,7 +9949,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor case Tpointer: if (t1b.isPtrToFunction()) { - error(exp.loc, "cannot index function pointer `%s`", exp.e1.toChars()); + error(exp.loc, "cannot index function pointer `%s`", exp.e1.toErrMsg()); return setError(); } exp.e2 = exp.e2.implicitCastTo(sc, Type.tsize_t); @@ -10078,7 +10046,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor return; } default: - error(exp.loc, "`%s` must be an array or pointer type, not `%s`", exp.e1.toChars(), exp.e1.type.toChars()); + error(exp.loc, "`%s` must be an array or pointer type, not `%s`", exp.e1.toErrMsg(), exp.e1.type.toChars()); return setError(); } @@ -10156,7 +10124,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor if (exp.e1.op == EXP.slice) { const(char)* s = exp.op == EXP.plusPlus ? "increment" : "decrement"; - error(exp.loc, "cannot post-%s array slice `%s`, use pre-%s instead", s, exp.e1.toChars(), s); + error(exp.loc, "cannot post-%s array slice `%s`, use pre-%s instead", s, exp.e1.toErrMsg(), s); return setError(); } @@ -10909,7 +10877,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor if (newExp.newtype && newExp.newtype == t1) { error(exp.loc, "cannot implicitly convert expression `%s` of type `%s` to `%s`", - newExp.toChars(), newExp.type.toChars(), t1.toChars()); + newExp.toErrMsg(), newExp.type.toChars(), t1.toChars()); errorSupplemental(exp.loc, "Perhaps remove the `new` keyword?"); return setError(); } @@ -11200,6 +11168,11 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor exp.e2 = e2x; t1 = e1x.type.toBasetype(); } + else if (t1.ty == Taarray) + { + // when assigning a constant, the need for TypeInfo might change + semanticTypeInfo(sc, t1); + } /* Check the mutability of e1. */ if (auto ale = exp.e1.isArrayLengthExp()) @@ -11248,14 +11221,6 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor id = id.expressionSemantic(sc); auto arguments = new Expressions(); - arguments.reserve(5); - 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(ale.e1); arguments.push(exp.e2); @@ -11282,7 +11247,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor if (exp.op == EXP.assign && !tn.baseElemOf().isAssignable()) { error(exp.loc, "slice `%s` is not mutable, struct `%s` has immutable members", - exp.e1.toChars(), tn.baseElemOf().toChars()); + exp.e1.toErrMsg(), tn.baseElemOf().toChars()); result = ErrorExp.get(); return; } @@ -11305,7 +11270,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor if (tn && !tn.baseElemOf().isAssignable()) { error(exp.loc, "array `%s` is not mutable, struct `%s` has immutable members", - exp.e1.toChars(), tn.baseElemOf().toChars()); + exp.e1.toErrMsg(), tn.baseElemOf().toChars()); result = ErrorExp.get(); return; } @@ -11375,7 +11340,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor uinteger_t dim2 = tsa2.dim.toInteger(); if (dim1 != dim2) { - error(exp.loc, "mismatched array lengths %d and %d for assignment `%s`", cast(int)dim1, cast(int)dim2, exp.toChars()); + error(exp.loc, "mismatched array lengths %d and %d for assignment `%s`", cast(int)dim1, cast(int)dim2, exp.toErrMsg()); return setError(); } } @@ -11451,7 +11416,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor // offer more information about the cause of the problem errorSupplemental(exp.loc, "`%s` is the first assignment of `%s` therefore it represents its initialization", - exp.toChars(), exp.e1.toChars()); + exp.toErrMsg(), exp.e1.toErrMsg()); errorSupplemental(exp.loc, "`opAssign` methods are not used for initialization, but for subsequent assignments"); } @@ -11973,15 +11938,6 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor id = new DotIdExp(exp.loc, id, hook); auto arguments = new Expressions(); - arguments.reserve(5); - 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(exp.e1); arguments.push(exp.e2); Expression ce = new CallExp(exp.loc, id, arguments); @@ -12016,15 +11972,6 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor id = new DotIdExp(exp.loc, id, hook); auto arguments = new Expressions(); - arguments.reserve(5); - 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())); - } - Expression eValue1; Expression value1 = extractSideEffect(sc, "__appendtmp", eValue1, exp.e1); @@ -12368,7 +12315,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor if (hook == Id._d_arraycatnTX) arguments.pushSlice((*callExp.arguments)[]); else - arguments.pushSlice((*callExp.arguments)[3 .. $]); + arguments.pushSlice((*callExp.arguments)[0 .. $ - 3]); } } else @@ -12376,15 +12323,6 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor } auto arguments = new Expressions(); - if (useTraceGCHook) - { - 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())); - } - handleCatArgument(arguments, exp.e1, exp.type.toBasetype(), false); handleCatArgument(arguments, exp.e2, exp.type.toBasetype(), true); @@ -12796,7 +12734,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor Module mmath = Module.loadStdMath(); if (!mmath) { - error(e.loc, "`%s` requires `std.math` for `^^` operators", e.toChars()); + error(e.loc, "`%s` requires `std.math` for `^^` operators", e.toErrMsg()); return setError(); } e = new ScopeExp(exp.loc, mmath); @@ -12970,7 +12908,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor if (e2x.op == EXP.type || e2x.op == EXP.scope_) { - error(exp.loc, "`%s` is not an expression", exp.e2.toChars()); + error(exp.loc, "`%s` is not an expression", exp.e2.toErrMsg()); return setError(); } if (e1x.op == EXP.error || e1x.type.ty == Tnoreturn) @@ -13137,7 +13075,10 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor exp.e1 = exp.e1.implicitCastTo(sc, ta.index); } - semanticTypeInfo(sc, ta.index); + // even though the glue layer only needs the type info of the index, + // this might be the first time an AA literal is accessed, so check + // the full type info + semanticTypeInfo(sc, ta); // Return type is pointer to value exp.type = ta.nextOf().pointerTo(); @@ -13152,7 +13093,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor errorSupplemental(exp.loc, "`in` is only allowed on associative arrays"); const(char)* slice = (t2b.ty == Tsarray) ? "[]" : ""; errorSupplemental(exp.loc, "perhaps use `std.algorithm.find(%s, %s%s)` instead", - exp.e1.toChars(), exp.e2.toChars(), slice); + exp.e1.toErrMsg(), exp.e2.toErrMsg(), slice); return; default: @@ -13374,8 +13315,9 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor } if (exp.e1.type.toBasetype().ty == Taarray) + { semanticTypeInfo(sc, exp.e1.type.toBasetype()); - + } if (!target.isVectorOpSupported(t1, exp.op, t2)) { @@ -13998,12 +13940,12 @@ private Expression dotIdSemanticPropX(DotIdExp exp, Scope* sc) // Template has no built-in properties except for 'stringof'. if ((exp.e1.isDotTemplateExp() || exp.e1.isTemplateExp()) && exp.ident != Id.stringof) { - error(exp.loc, "template `%s` does not have property `%s`", exp.e1.toChars(), exp.ident.toChars()); + error(exp.loc, "template `%s` does not have property `%s`", exp.e1.toErrMsg(), exp.ident.toChars()); return ErrorExp.get(); } if (!exp.e1.type) { - error(exp.loc, "expression `%s` does not have property `%s`", exp.e1.toChars(), exp.ident.toChars()); + error(exp.loc, "expression `%s` does not have property `%s`", exp.e1.toErrMsg(), exp.ident.toChars()); return ErrorExp.get(); } @@ -14405,7 +14347,7 @@ Expression dotTemplateSemanticProp(DotTemplateInstanceExp exp, Scope* sc, bool g Expression notTemplate() { - error(exp.loc, "`%s` isn't a template", e.toChars()); + error(exp.loc, "`%s` isn't a template", e.toErrMsg()); return errorExp(); } @@ -14720,7 +14662,7 @@ MATCH matchType(FuncExp funcExp, Type to, Scope* sc, FuncExp* presult, ErrorSink { auto ts = toAutoQualChars(tx, to); eSink.error(loc, "cannot implicitly convert expression `%s` of type `%s` to `%s`", - funcExp.toChars(), ts[0], ts[1]); + funcExp.toErrMsg(), ts[0], ts[1]); } return m; } @@ -14733,7 +14675,7 @@ private bool checkScalar(Expression e) return true; if (!e.type.isScalar()) { - error(e.loc, "`%s` is not a scalar, it is a `%s`", e.toChars(), e.type.toChars()); + error(e.loc, "`%s` is not a scalar, it is a `%s`", e.toErrMsg(), e.type.toChars()); return true; } return e.checkValue(); @@ -14747,7 +14689,7 @@ private bool checkNoBool(Expression e) return true; if (e.type.toBasetype().ty == Tbool) { - error(e.loc, "operation not allowed on `bool` `%s`", e.toChars()); + error(e.loc, "operation not allowed on `bool` `%s`", e.toErrMsg()); return true; } return false; @@ -14761,7 +14703,7 @@ private bool checkIntegral(Expression e) return true; if (!e.type.isIntegral()) { - error(e.loc, "`%s` is not of integral type, it is a `%s`", e.toChars(), e.type.toChars()); + error(e.loc, "`%s` is not of integral type, it is a `%s`", e.toErrMsg(), e.type.toChars()); return true; } return e.checkValue(); @@ -14779,7 +14721,7 @@ private bool checkArithmetic(Expression e, EXP op) const char* msg = e.type.isAggregate() ? "operator `%s` is not defined for `%s` of type `%s`" : "illegal operator `%s` for `%s` of type `%s`"; - error(e.loc, msg, EXPtoString(op).ptr, e.toChars(), e.type.toChars()); + error(e.loc, msg, EXPtoString(op).ptr, e.toErrMsg(), e.type.toChars()); return true; } @@ -14862,7 +14804,7 @@ bool checkValue(Expression e) { if (auto te = e.isTypeExp()) { - error(e.loc, "type `%s` has no value", e.toChars()); + error(e.loc, "type `%s` has no value", e.toErrMsg()); if (!e.type.isOpaqueType) errorSupplemental(e.loc, "perhaps use `%s.init`", e.toChars()); return true; @@ -14874,7 +14816,7 @@ bool checkValue(Expression e) dtie.ti.semantictiargsdone && dtie.ti.semanticRun == PASS.initial) - error(e.loc, "partial %s `%s` has no value", dtie.ti.kind(), e.toChars()); + error(e.loc, "partial %s `%s` has no value", dtie.ti.kind(), e.toErrMsg()); else error(e.loc, "%s `%s` has no value", dtie.ti.kind(), dtie.ti.toChars()); return true; @@ -14904,13 +14846,13 @@ bool checkValue(Expression e) if (auto dte = e.isDotTemplateExp()) { - error(e.loc, "%s `%s` has no value", dte.td.kind(), e.toChars()); + error(e.loc, "%s `%s` has no value", dte.td.kind(), e.toErrMsg()); return true; } if (e.type && e.type.toBasetype().ty == Tvoid) { - error(e.loc, "expression `%s` is `void` and has no value", e.toChars()); + error(e.loc, "expression `%s` is `void` and has no value", e.toErrMsg()); //print(); assert(0); if (!global.gag) e.type = Type.terror; @@ -14970,7 +14912,7 @@ bool checkSharedAccess(Expression e, Scope* sc, bool returnRef = false) bool sharedError(Expression e) { // https://dlang.org/phobos/core_atomic.html - error(e.loc, "direct access to shared `%s` is not allowed, see `core.atomic`", e.toChars()); + error(e.loc, "direct access to shared `%s` is not allowed, see `core.atomic`", e.toErrMsg()); return true; } @@ -15494,9 +15436,9 @@ private Expression toLvalueImpl(Expression _this, Scope* sc, const(char)* action if (e.op == EXP.type) 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()); + error(_this.loc, "cannot %s template `%s`, perhaps instantiate it first", action, e.toErrMsg()); else - error(_this.loc, "cannot %s expression `%s` because it is not an lvalue", action, e.toChars()); + error(_this.loc, "cannot %s expression `%s` because it is not an lvalue", action, e.toErrMsg()); return ErrorExp.get(); } @@ -15505,7 +15447,7 @@ private Expression toLvalueImpl(Expression _this, Scope* sc, const(char)* action { if (!_this.loc.isValid()) _this.loc = e.loc; - error(e.loc, "cannot %s constant `%s`", action, e.toChars()); + error(e.loc, "cannot %s constant `%s`", action, e.toErrMsg()); return ErrorExp.get(); } @@ -15930,12 +15872,12 @@ private Expression modifiableLvalueImpl(Expression _this, Scope* sc, Expression break; if (!ff.type.isMutable) { - error(exp.loc, "cannot modify `%s` in `%s` function", exp.toChars(), MODtoChars(type.mod)); + error(exp.loc, "cannot modify `%s` in `%s` function", exp.toErrMsg(), MODtoChars(type.mod)); return ErrorExp.get(); } } } - error(exp.loc, "cannot modify `%s` expression `%s`", MODtoChars(type.mod), exp.toChars()); + error(exp.loc, "cannot modify `%s` expression `%s`", MODtoChars(type.mod), exp.toErrMsg()); return ErrorExp.get(); } else if (!type.isAssignable()) @@ -15950,7 +15892,7 @@ private Expression modifiableLvalueImpl(Expression _this, Scope* sc, Expression Expression visitString(StringExp exp) { - error(exp.loc, "cannot modify string literal `%s`", exp.toChars()); + error(exp.loc, "cannot modify string literal `%s`", exp.toErrMsg()); return ErrorExp.get(); } @@ -15959,7 +15901,7 @@ private Expression modifiableLvalueImpl(Expression _this, Scope* sc, Expression //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()); + error(exp.loc, "cannot modify manifest constant `%s`", exp.toErrMsg()); return ErrorExp.get(); } // See if this expression is a modifiable lvalue (i.e. not const) @@ -15988,7 +15930,7 @@ private Expression modifiableLvalueImpl(Expression _this, Scope* sc, Expression Expression visitSlice(SliceExp exp) { - error(exp.loc, "slice expression `%s` is not a modifiable lvalue", exp.toChars()); + error(exp.loc, "slice expression `%s` is not a modifiable lvalue", exp.toErrMsg()); return exp; } @@ -16030,7 +15972,7 @@ private Expression modifiableLvalueImpl(Expression _this, Scope* sc, Expression { if (!exp.e1.isLvalue() && !exp.e2.isLvalue()) { - error(exp.loc, "conditional expression `%s` is not a modifiable lvalue", exp.toChars()); + error(exp.loc, "conditional expression `%s` is not a modifiable lvalue", exp.toErrMsg()); return ErrorExp.get(); } exp.e1 = exp.e1.modifiableLvalue(sc); @@ -16071,7 +16013,7 @@ private bool checkAddressVar(Scope* sc, Expression exp, VarDeclaration v) if (!v.canTakeAddressOf()) { - error(exp.loc, "cannot take address of `%s`", exp.toChars()); + error(exp.loc, "cannot take address of `%s`", exp.toErrMsg()); return false; } if (sc.func && !sc.intypeof && !v.isDataseg()) @@ -16133,9 +16075,9 @@ bool checkAddressable(Expression e, Scope* sc) if (ex.isVarExp().var.storage_class & STC.register) { if (e.isIndexExp()) - error(e.loc, "cannot index through register variable `%s`", ex.toChars()); + error(e.loc, "cannot index through register variable `%s`", ex.toErrMsg()); else - error(e.loc, "cannot take address of register variable `%s`", ex.toChars()); + error(e.loc, "cannot take address of register variable `%s`", ex.toErrMsg()); return false; } } @@ -16629,7 +16571,7 @@ bool evalStaticCondition(Scope* sc, Expression original, Expression e, out bool if (opt.isEmpty()) { if (!e.type.isTypeError()) - error(e.loc, "expression `%s` is not constant", e.toChars()); + error(e.loc, "expression `%s` is not constant", e.toErrMsg()); errors = true; return false; } @@ -16916,6 +16858,9 @@ void semanticTypeInfo(Scope* sc, Type t) { semanticTypeInfo(sc, t.index); semanticTypeInfo(sc, t.next); + + if (global.params.useTypeInfo) + getTypeInfoType(t.loc, t, sc); } void visitStruct(TypeStruct t) diff --git a/gcc/d/dmd/file_manager.d b/gcc/d/dmd/file_manager.d index 7f39ec91..f2116e5 100644 --- a/gcc/d/dmd/file_manager.d +++ b/gcc/d/dmd/file_manager.d @@ -101,8 +101,10 @@ private struct PathCache */ bool exists = true; auto st = PathStack(filespec); - while (st.up) { - if (auto cached = pathStatus.lookup(st.cur)) { + while (st.up) + { + if (auto cached = pathStatus.lookup(st.cur)) + { exists = cached.value; break; } @@ -112,7 +114,8 @@ private struct PathCache * Once a directory is found to not exist, all the directories * to the right of it do not exist */ - while (st.down) { + while (st.down) + { if (!exists) pathStatus.insert(st.cur, false); else @@ -218,17 +221,19 @@ nothrow: const(char)[] n = FileName.combine(p, sdi); - if (!pathCache.pathExists(n)) { + if (!pathCache.pathExists(n)) + { FileName.free(n.ptr); continue; // no need to check for anything else. } - if (FileName.exists(n) == 1) { + if (FileName.exists(n) == 1) return n; - } + FileName.free(n.ptr); n = FileName.combine(p, sd); - if (FileName.exists(n) == 1) { + if (FileName.exists(n) == 1) + { whichPathFoundThis = pathIndex; return n; } @@ -241,14 +246,16 @@ nothrow: if (pathCache.isExistingPath(n)) { const n2i = FileName.combine(n, package_di); - if (FileName.exists(n2i) == 1) { + if (FileName.exists(n2i) == 1) + { whichPathFoundThis = pathIndex; return n2i; } FileName.free(n2i.ptr); const n2 = FileName.combine(n, package_d); - if (FileName.exists(n2) == 1) { + if (FileName.exists(n2) == 1) + { whichPathFoundThis = pathIndex; return n2; } @@ -272,14 +279,16 @@ nothrow: const p = entry.path.toDString(); const(char)[] n = FileName.combine(p, si); - if (FileName.exists(n) == 1) { + if (FileName.exists(n) == 1) + { whichPathFoundThis = pathIndex; return n; } FileName.free(n.ptr); n = FileName.combine(p, sc); - if (FileName.exists(n) == 1) { + if (FileName.exists(n) == 1) + { whichPathFoundThis = pathIndex; return n; } diff --git a/gcc/d/dmd/func.d b/gcc/d/dmd/func.d index 80312f2..e5b72e2 100644 --- a/gcc/d/dmd/func.d +++ b/gcc/d/dmd/func.d @@ -1883,10 +1883,10 @@ struct AttributeViolation assert(args.length <= 4); // expand if necessary OutBuffer buf; buf.printf(fmt, - args.length > 0 && args[0] ? args[0].toChars() : "", - args.length > 1 && args[1] ? args[1].toChars() : "", - args.length > 2 && args[2] ? args[2].toChars() : "", - args.length > 3 && args[3] ? args[3].toChars() : "", + args.length > 0 && args[0] ? args[0].toErrMsg() : "", + args.length > 1 && args[1] ? args[1].toErrMsg() : "", + args.length > 2 && args[2] ? args[2].toErrMsg() : "", + args.length > 3 && args[3] ? args[3].toErrMsg() : "", ); this.action = buf.extractSlice(); } diff --git a/gcc/d/dmd/hdrgen.d b/gcc/d/dmd/hdrgen.d index c0fcf64..0ef955a 100644 --- a/gcc/d/dmd/hdrgen.d +++ b/gcc/d/dmd/hdrgen.d @@ -59,10 +59,12 @@ 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 inCAlias; /// Set to prevent ImportC translating typedefs as `alias X = X` bool doFuncBodies; /// include function bodies in output bool vcg_ast; /// write out codegen-ast bool skipConstraints; // skip constraints when doing templates bool showOneMember = true; + bool errorMsg; /// true if formatting for inside an error message bool fullQual; /// fully qualify types when printing int tpltMember; @@ -96,6 +98,87 @@ void genhdrfile(Module m, bool doFuncBodies, ref OutBuffer buf) toCBuffer(m, buf, hgs); } +/** + * Convert `o` to a string for error messages. + * Params: + * e = object to convert + * Returns: string representation of `e` + */ +const(char)* toErrMsg(const RootObject o) +{ + if (auto e = o.isExpression()) + return toErrMsg(e); + if (auto d = o.isDsymbol()) + return toErrMsg(d); + if (auto t = o.isType()) + return t.toChars(); + if (auto id = o.isIdentifier()) + return id.toChars(); + assert(0); +} + +/// ditto +const(char)* toErrMsg(const Expression e) +{ + HdrGenState hgs; + hgs.errorMsg = true; + OutBuffer buf; + toCBuffer(e, buf, hgs); + truncateForError(buf, 60); + + return buf.extractChars(); +} + +/// ditto +const(char)* toErrMsg(const Dsymbol d) +{ + if (d.isFuncDeclaration() || d.isTemplateInstance()) + { + if (d.ident && d.ident.toString.startsWith("__") && !d.isCtorDeclaration()) + { + HdrGenState hgs; + hgs.errorMsg = true; + OutBuffer buf; + toCBuffer(cast() d, buf, hgs); + truncateForError(buf, 80); + return buf.extractChars(); + } + } + + return d.toChars(); +} + +/** + * Make the content of `buf` fit inline for an error message. + * Params: + * buf = buffer with text to modify + * maxLength = truncate text when it exceeds this length + */ +private void truncateForError(ref OutBuffer buf, size_t maxLength) +{ + // Remove newlines, escape backticks ` by doubling them + for (size_t i = 0; i < buf.length; i++) + { + if (buf[i] == '\r') + buf.remove(i, 1); + if (buf[i] == '\n') + buf.peekSlice[i] = ' '; + if (buf[i] == '`') + i = buf.insert(i, "`"); + } + + // Strip trailing whitespace + while (buf.length && buf[$-1] == ' ') + buf.setsize(buf.length - 1); + + // Truncate + if (buf.length > maxLength) + { + buf.setsize(maxLength - 3); + buf.writestring("..."); + } +} + /*************************************** * Turn a Statement into a string suitable for printf. * Leaks memory. @@ -1658,7 +1741,7 @@ void toCBuffer(Dsymbol s, ref OutBuffer buf, ref HdrGenState hgs) { if (d.storage_class & STC.local) return; - if (d.adFlags & d.hidden) + if (d.hidden) return; buf.writestring("alias "); if (d.aliassym) @@ -1695,7 +1778,9 @@ void toCBuffer(Dsymbol s, ref OutBuffer buf, ref HdrGenState hgs) buf.writestring(" = "); if (stcToBuffer(buf, d.storage_class)) buf.writeByte(' '); + hgs.inCAlias = hgs.importcHdr; typeToBuffer(d.type, null, buf, hgs); + hgs.inCAlias = false; hgs.declstring = false; } buf.writeByte(';'); @@ -1772,7 +1857,7 @@ void toCBuffer(Dsymbol s, ref OutBuffer buf, ref HdrGenState hgs) buf.writestring("__error"); return; } - if (f.tok != TOK.reserved) + if (f.tok != TOK.reserved && !hgs.errorMsg) { buf.writestring(f.kind()); buf.writeByte(' '); @@ -1789,8 +1874,9 @@ void toCBuffer(Dsymbol s, ref OutBuffer buf, ref HdrGenState hgs) buf.writeByte(' '); buf.writestring(str); } - tf.attributesApply(&printAttribute); + if (!hgs.errorMsg) + tf.attributesApply(&printAttribute); CompoundStatement cs = f.fbody.isCompoundStatement(); Statement s1; @@ -4366,6 +4452,11 @@ private void typeToBufferx(Type t, ref OutBuffer buf, ref HdrGenState hgs) buf.writestring("noreturn"); } + if (hgs.importcHdr && !hgs.inCAlias && t.mcache && t.mcache.typedefIdent) + { + buf.writestring(t.mcache.typedefIdent.toString()); + return; + } switch (t.ty) { diff --git a/gcc/d/dmd/id.d b/gcc/d/dmd/id.d index 9833e198..fa7fe1d 100644 --- a/gcc/d/dmd/id.d +++ b/gcc/d/dmd/id.d @@ -166,6 +166,7 @@ immutable Msgtable[] msgtable = { "xopCmp", "__xopCmp" }, { "xtoHash", "__xtoHash" }, { "__tmpfordtor" }, + { "Entry" }, { "LINE", "__LINE__" }, { "FILE", "__FILE__" }, diff --git a/gcc/d/dmd/identifier.d b/gcc/d/dmd/identifier.d index 231aa58..9ef8285 100644 --- a/gcc/d/dmd/identifier.d +++ b/gcc/d/dmd/identifier.d @@ -248,13 +248,14 @@ nothrow: * directly, but that would unnecessary lengthen symbols names. See issue: * https://issues.dlang.org/show_bug.cgi?id=23722 */ - static struct Key { uint fileOffset; string prefix; string parent; } + static struct Key { string locKey; string prefix; string parent; } __gshared uint[Key] counters; + string locKey = cast(string) (sl.filename ~ idBuf[]); static if (__traits(compiles, counters.update(Key.init, () => 0u, (ref uint a) => 0u))) { // 2.082+ - counters.update(Key(loc.fileOffset, prefix, parent), + counters.update(Key(locKey, prefix, parent), () => 1u, // insertion (ref uint counter) // update { @@ -266,7 +267,7 @@ nothrow: } else { - const key = Key(loc.fileOffset, prefix, parent); + const key = Key(locKey, prefix, parent); if (auto pCounter = key in counters) { idBuf.writestring("_"); diff --git a/gcc/d/dmd/initsem.d b/gcc/d/dmd/initsem.d index 467b796..cda4088 100644 --- a/gcc/d/dmd/initsem.d +++ b/gcc/d/dmd/initsem.d @@ -585,7 +585,7 @@ Initializer initializerSemantic(Initializer init, Scope* sc, ref Type tx, NeedIn const errors = global.startGagging(); i.exp = i.exp.implicitCastTo(sc, t); if (global.endGagging(errors)) - error(currExp.loc, "cannot implicitly convert expression `%s` of type `%s` to `%s`", currExp.toChars(), et.toChars(), t.toChars()); + error(currExp.loc, "cannot implicitly convert expression `%s` of type `%s` to `%s`", currExp.toErrMsg(), et.toChars(), t.toChars()); } } L1: diff --git a/gcc/d/dmd/json.d b/gcc/d/dmd/json.d index 05924f7..4900320 100644 --- a/gcc/d/dmd/json.d +++ b/gcc/d/dmd/json.d @@ -41,10 +41,13 @@ import dmd.root.string; import dmd.target; import dmd.visitor; -version(Windows) { +version(Windows) +{ extern (C) char* _getcwd(char* buffer, size_t maxlen); alias getcwd = _getcwd; -} else { +} +else +{ import core.sys.posix.unistd : getcwd; } diff --git a/gcc/d/dmd/lambdacomp.d b/gcc/d/dmd/lambdacomp.d index 90c794e..96a1780 100644 --- a/gcc/d/dmd/lambdacomp.d +++ b/gcc/d/dmd/lambdacomp.d @@ -445,7 +445,8 @@ public: visitType(p.type); } - override void visit(StructLiteralExp e) { + override void visit(StructLiteralExp e) + { static if (LOG) printf("StructLiteralExp: %s\n", e.toChars); diff --git a/gcc/d/dmd/lexer.d b/gcc/d/dmd/lexer.d index 61b4f41..51e597c 100644 --- a/gcc/d/dmd/lexer.d +++ b/gcc/d/dmd/lexer.d @@ -867,7 +867,7 @@ class Lexer case 0: case 0x1A: error(t.loc, "unterminated /* */ comment"); - p = end; + //p = end; t.loc = loc(); t.value = TOK.endOfFile; return; @@ -927,7 +927,7 @@ class Lexer getDocComment(t, lastLine == startLoc.linnum, startLoc.linnum - lastDocLine > 1); lastDocLine = linnum; } - p = end; + //p = end; t.loc = loc(); t.value = TOK.endOfFile; return; @@ -1003,7 +1003,7 @@ class Lexer case 0: case 0x1A: error(t.loc, "unterminated /+ +/ comment"); - p = end; + //p = end; t.loc = loc(); t.value = TOK.endOfFile; return; @@ -3441,9 +3441,8 @@ class Lexer int linestart = 0; if (ct == '/') { - if (q < qend && *q == ' ') { + if (q < qend && *q == ' ') ++q; - } } else if (q < qend) { diff --git a/gcc/d/dmd/location.d b/gcc/d/dmd/location.d index 8a27541..ef5430f 100644 --- a/gcc/d/dmd/location.d +++ b/gcc/d/dmd/location.d @@ -64,7 +64,7 @@ nothrow: extern (C++) static Loc singleFilename(const char* filename) { Loc result; - locFileTable ~= BaseLoc(filename.toDString, locIndex, 0, [0]); + locFileTable ~= new BaseLoc(filename.toDString, locIndex, 0, [0]); result.index = locIndex++; return result; } @@ -95,7 +95,19 @@ nothrow: */ extern (C++) const(char)* filename() const @nogc { - return SourceLoc(this).filename.ptr; // _filename; + if (this.index == 0) + return null; + + const i = fileTableIndex(this.index); + if (locFileTable[i].substitutions.length > 0) + { + const si = locFileTable[i].getSubstitutionIndex(this.index - locFileTable[i].startIndex); + const fname = locFileTable[i].substitutions[si].filename; + if (fname.length > 0) + return fname.ptr; + } + + return locFileTable[i].filename.ptr; } extern (C++) const(char)* toChars( @@ -293,11 +305,11 @@ private size_t fileTableIndex(uint index) nothrow @nogc */ BaseLoc* newBaseLoc(const(char)* filename, size_t size) nothrow { - locFileTable ~= BaseLoc(filename.toDString, locIndex, 1, [0]); + locFileTable ~= new BaseLoc(filename.toDString, locIndex, 1, [0]); // Careful: the endloc of a FuncDeclaration can // point to 1 past the very last byte in the file, so account for that locIndex += size + 1; - return &locFileTable[$ - 1]; + return locFileTable[$ - 1]; } /** @@ -385,7 +397,23 @@ struct BaseLoc if (substitutions.length == 0) return loc; - const offset = loc.fileOffset; + const i = getSubstitutionIndex(loc.fileOffset); + if (substitutions[i].filename.length > 0) + loc.filename = substitutions[i].filename; + loc.linnum += substitutions[i].startLine; + return loc; + } + + /// Resolve an offset into this file to a filename + line + column + private SourceLoc getSourceLoc(uint offset) @nogc + { + const i = getLineIndex(offset); + const sl = SourceLoc(filename, cast(int) (i + startLine), cast(int) (1 + offset - lines[i]), offset); + return substitute(sl); + } + + private size_t getSubstitutionIndex(uint offset) @nogc + { size_t lo = 0; size_t hi = substitutions.length + -1; size_t mid = 0; @@ -395,12 +423,7 @@ struct BaseLoc if (substitutions[mid].startIndex <= offset) { if (mid == substitutions.length - 1 || substitutions[mid + 1].startIndex > offset) - { - if (substitutions[mid].filename.length > 0) - loc.filename = substitutions[mid].filename; - loc.linnum += substitutions[mid].startLine; - return loc; - } + return mid; lo = mid + 1; } @@ -412,14 +435,6 @@ struct BaseLoc assert(0); } - /// Resolve an offset into this file to a filename + line + column - private SourceLoc getSourceLoc(uint offset) @nogc - { - const i = getLineIndex(offset); - const sl = SourceLoc(filename, cast(int) (i + startLine), cast(int) (1 + offset - lines[i]), offset); - return substitute(sl); - } - /// Binary search the index in `this.lines` corresponding to `offset` private size_t getLineIndex(uint offset) @nogc { @@ -449,4 +464,4 @@ struct BaseLoc private __gshared uint locIndex = 1; // Global mapping of Loc indices to source file offset/line/column, see `BaseLoc` -private __gshared BaseLoc[] locFileTable; +private __gshared BaseLoc*[] locFileTable; diff --git a/gcc/d/dmd/mtype.d b/gcc/d/dmd/mtype.d index 1cebcc8..84899d0 100644 --- a/gcc/d/dmd/mtype.d +++ b/gcc/d/dmd/mtype.d @@ -299,13 +299,16 @@ extern (C++) abstract class Type : ASTNode Type wcto; // MODFlags.wildconst Type swto; // MODFlags.shared_ | MODFlags.wild Type swcto; // MODFlags.shared_ | MODFlags.wildconst + Type pto; // merged pointer to this type + Type rto; // reference to this type + Type arrayof; // array of this type + + // ImportC: store the name of the typedef resolving to this type + // So `uint8_t x;` will be printed as `uint8_t x;` and not as the resolved `ubyte x;` + Identifier typedefIdent; } Mcache* mcache; - Type pto; // merged pointer to this type - Type rto; // reference to this type - Type arrayof; // array of this type - TypeInfoDeclaration vtinfo; // TypeInfo object for this Type void* ctype; // for back end @@ -762,9 +765,6 @@ extern (C++) abstract class Type : ASTNode memcpy(cast(void*)t, cast(void*)this, sz); // t.mod = NULL; // leave mod unchanged t.deco = null; - t.arrayof = null; - t.pto = null; - t.rto = null; t.vtinfo = null; t.ctype = null; t.mcache = null; @@ -2959,9 +2959,6 @@ extern (C++) final class TypeIdentifier : TypeQualified { Identifier ident; - // The symbol representing this identifier, before alias resolution - Dsymbol originalSymbol; - extern (D) this(Loc loc, Identifier ident) { super(Tident, loc); @@ -3870,7 +3867,8 @@ extern (C++) struct ParameterList foreach (_, p1; cast() this) { auto p2 = other[idx++]; - if (!p2 || p1 != p2) { + if (!p2 || p1 != p2) + { diff = true; break; } diff --git a/gcc/d/dmd/mtype.h b/gcc/d/dmd/mtype.h index 0cf08e7..990f8d4 100644 --- a/gcc/d/dmd/mtype.h +++ b/gcc/d/dmd/mtype.h @@ -146,9 +146,6 @@ public: MOD mod; // modifiers MODxxxx char *deco; void* mcache; - Type *pto; // merged pointer to this type - Type *rto; // reference to this type - Type *arrayof; // array of this type TypeInfoDeclaration *vtinfo; // TypeInfo object for this Type type *ctype; // for back end @@ -630,7 +627,6 @@ class TypeIdentifier final : public TypeQualified { public: Identifier *ident; - Dsymbol *originalSymbol; // The symbol representing this identifier, before alias resolution static TypeIdentifier *create(Loc loc, Identifier *ident); const char *kind() override; diff --git a/gcc/d/dmd/parse.d b/gcc/d/dmd/parse.d index 121f990..33e0e5a 100644 --- a/gcc/d/dmd/parse.d +++ b/gcc/d/dmd/parse.d @@ -1041,6 +1041,30 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer nextToken(); continue; + // The following are all errors, the cases are just for better error messages than the default case + case TOK.return_: + case TOK.goto_: + case TOK.break_: + case TOK.continue_: + error("`%s` statement must be inside function scope", token.toChars()); + goto Lerror; + case TOK.asm_: + case TOK.do_: + case TOK.for_: + case TOK.foreach_: + case TOK.foreach_reverse_: + case TOK.if_: + case TOK.switch_: + case TOK.try_: + case TOK.while_: + error("`%s` statement must be inside function scope", token.toChars()); + if (peekNext() == TOK.leftParenthesis || peekNext() == TOK.leftCurly) + { + parseStatement(0); + s = null; + continue; + } + goto Lerror; default: error("declaration expected, not `%s`", token.toChars()); Lerror: @@ -1504,28 +1528,26 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer if (token.value != TOK.identifier) { error("identifier expected following `template`"); - goto Lerr; + return null; } id = token.ident; nextToken(); tpl = parseTemplateParameterList(); if (!tpl) - goto Lerr; + return null; constraint = parseConstraint(); if (token.value != TOK.leftCurly) { error("`{` expected after template parameter list, not `%s`", token.toChars()); /* } */ - goto Lerr; + nextToken(); + return null; } decldefs = parseBlock(null); tempdecl = new AST.TemplateDeclaration(loc, id, tpl, constraint, decldefs, ismixin); return tempdecl; - - Lerr: - return null; } /****************************************** @@ -4509,7 +4531,7 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer if (ident) checkCstyleTypeSyntax(loc, t, alt, ident); else if (!isThis && (t != AST.Type.terror)) - noIdentifierForDeclarator(t); + noIdentifierForDeclarator(t, token); if (isAliasDeclaration) { @@ -4571,6 +4593,7 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer default: error("semicolon expected to close `alias` declaration, not `%s`", token.toChars()); + nextToken(); break; } } @@ -4734,11 +4757,12 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer return a; } - /// Report an error that a declaration of type `t` is missing an identifier + /// Report an error that a declaration of type `t` is missing an identifier and got `tok` instead /// The parser is expected to sit on the next token after the type. - private void noIdentifierForDeclarator(AST.Type t) + private void noIdentifierForDeclarator(AST.Type t, Token tok) { - error("no identifier for declarator `%s`", t.toChars()); + error("variable name expected after type `%s`, not `%s`", t.toChars(), tok.toChars); + // A common mistake is to use a reserved keyword as an identifier, e.g. `in` or `out` if (token.isKeyword) { @@ -5016,6 +5040,7 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer default: error("semicolon expected to close `alias` declaration, not `%s`", token.toChars()); + nextToken(); break; } break; @@ -5356,9 +5381,14 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer error("template constraint must follow parameter lists and attributes"); else error("cannot use function constraints for non-template functions. Use `static if` instead"); + + parseConstraint(); } else + { error("semicolon expected following function declaration, not `%s`", token.toChars()); + nextToken(); + } } break; } @@ -5542,7 +5572,7 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer } at = parseType(&ai); if (!ai) - noIdentifierForDeclarator(at); + noIdentifierForDeclarator(at, token); Larg: auto p = new AST.Parameter(aloc, storageClass, at, ai, null, null); parameters.push(p); diff --git a/gcc/d/dmd/root/string.d b/gcc/d/dmd/root/string.d index 847af0e..be606c4 100644 --- a/gcc/d/dmd/root/string.d +++ b/gcc/d/dmd/root/string.d @@ -377,9 +377,9 @@ auto splitLines(const char[] text) public const(char)[] front() { advance(); - if (index > eolIndex || index >= text.length) { + if (index > eolIndex || index >= text.length) return ""; - } + return text[index .. eolIndex]; } diff --git a/gcc/d/dmd/semantic2.d b/gcc/d/dmd/semantic2.d index 31fc418..893dc1b 100644 --- a/gcc/d/dmd/semantic2.d +++ b/gcc/d/dmd/semantic2.d @@ -852,6 +852,8 @@ private extern(C++) final class StaticAAVisitor : SemanticTimeTransitiveVisitor loweredExp = loweredExp.ctfeInterpret(); aaExp.lowering = loweredExp; + + semanticTypeInfo(sc, loweredExp.type); } // https://issues.dlang.org/show_bug.cgi?id=24602 diff --git a/gcc/d/dmd/semantic3.d b/gcc/d/dmd/semantic3.d index 5d7f8bc..f7a7ce1 100644 --- a/gcc/d/dmd/semantic3.d +++ b/gcc/d/dmd/semantic3.d @@ -380,7 +380,7 @@ private extern(C++) final class Semantic3Visitor : Visitor if (!sc.intypeof) { if (fld.tok == TOK.delegate_) - .error(funcdecl.loc, "%s `%s` cannot be %s members", funcdecl.kind, funcdecl.toPrettyChars, ad.kind()); + .error(funcdecl.loc, "%s `%s` cannot be %s members", funcdecl.kind, funcdecl.toErrMsg, ad.kind()); else fld.tok = TOK.function_; } @@ -933,7 +933,37 @@ private extern(C++) final class Semantic3Visitor : Visitor // if a copy constructor is present, the return type conversion will be handled by it const hasCopyCtor = exp.type.ty == Tstruct && (cast(TypeStruct)exp.type).sym.hasCopyCtor; if (!hasCopyCtor || !exp.isLvalue()) - exp = exp.implicitCastTo(sc2, tret); + { + const errors = global.startGagging(); + auto implicitlyCastedExp = exp.implicitCastTo(sc2, tret); + global.endGagging(errors); + + // <https://github.com/dlang/dmd/issues/20888> + if (implicitlyCastedExp.isErrorExp()) + { + auto types = toAutoQualChars(exp.type, tret); + error( + exp.loc, + "return value `%s` of type `%s` does not match return type `%s`" + ~ ", and cannot be implicitly converted", + exp.toErrMsg(), + types[0], + types[1], + ); + + if (const func = exp.type.isFunction_Delegate_PtrToFunction()) + if (func.next.equals(tret)) + errorSupplemental( + exp.loc, + "Did you intend to call the %s?", + (exp.type.isPtrToFunction()) + ? "function pointer" + : exp.type.kind + ); + } + + exp = implicitlyCastedExp; + } exp = exp.optimize(WANTvalue); @@ -1375,7 +1405,7 @@ private extern(C++) final class Semantic3Visitor : Visitor } if (isCppNonMappableType(f.next.toBasetype())) { - .error(funcdecl.loc, "%s `%s` cannot return type `%s` because its linkage is `extern(C++)`", funcdecl.kind, funcdecl.toPrettyChars, f.next.toChars()); + .error(funcdecl.loc, "%s `%s` cannot return type `%s` because its linkage is `extern(C++)`", funcdecl.kind, funcdecl.toErrMsg(), f.next.toChars()); if (f.next.isTypeDArray()) errorSupplemental(funcdecl.loc, "slices are specific to D and do not have a counterpart representation in C++", f.next.toChars()); funcdecl.errors = true; @@ -1384,7 +1414,7 @@ private extern(C++) final class Semantic3Visitor : Visitor { if (isCppNonMappableType(param.type.toBasetype(), param)) { - .error(funcdecl.loc, "%s `%s` cannot have parameter of type `%s` because its linkage is `extern(C++)`", funcdecl.kind, funcdecl.toPrettyChars, param.type.toChars()); + .error(funcdecl.loc, "%s `%s` cannot have parameter of type `%s` because its linkage is `extern(C++)`", funcdecl.kind, funcdecl.toErrMsg(), param.type.toChars()); if (param.type.toBasetype().isTypeSArray()) errorSupplemental(funcdecl.loc, "perhaps use a `%s*` type instead", param.type.nextOf().mutableOf().unSharedOf().toChars()); @@ -1741,7 +1771,7 @@ extern (D) bool checkClosure(FuncDeclaration fd) } a.push(f); .errorSupplemental(f.loc, "%s `%s` closes over variable `%s`", - f.kind, f.toPrettyChars(), v.toChars()); + f.kind, f.toErrMsg(), v.toChars()); if (v.ident != Id.This) .errorSupplemental(v.loc, "`%s` declared here", v.toChars()); diff --git a/gcc/d/dmd/sideeffect.d b/gcc/d/dmd/sideeffect.d index 84b9e4e..659b0f4 100644 --- a/gcc/d/dmd/sideeffect.d +++ b/gcc/d/dmd/sideeffect.d @@ -20,6 +20,7 @@ import dmd.expressionsem; import dmd.func; import dmd.funcsem; import dmd.globals; +import dmd.hdrgen; import dmd.id; import dmd.identifier; import dmd.init; @@ -346,12 +347,13 @@ bool discardValue(Expression e) BinExp tmp = e.isBinExp(); assert(tmp); - error(e.loc, "the result of the equality expression `%s` is discarded", e.toChars()); + error(e.loc, "the result of the equality expression `%s` is discarded", e.toErrMsg()); bool seenSideEffect = false; foreach(expr; [tmp.e1, tmp.e2]) { - if (hasSideEffect(expr)) { - errorSupplemental(expr.loc, "note that `%s` may have a side effect", expr.toChars()); + if (hasSideEffect(expr)) + { + errorSupplemental(expr.loc, "note that `%s` may have a side effect", expr.toErrMsg()); seenSideEffect |= true; } } @@ -359,7 +361,7 @@ bool discardValue(Expression e) default: break; } - error(e.loc, "`%s` has no effect", e.toChars()); + error(e.loc, "`%s` has no effect", e.toErrMsg()); return true; } diff --git a/gcc/d/dmd/statementsem.d b/gcc/d/dmd/statementsem.d index 6a3bc38..4029fda 100644 --- a/gcc/d/dmd/statementsem.d +++ b/gcc/d/dmd/statementsem.d @@ -664,7 +664,7 @@ Statement statementSemanticVisit(Statement s, Scope* sc) const olderrors = global.startGagging(); discardValue(fs.increment); if (global.endGagging(olderrors)) - deprecation(fs.increment.loc, "`%s` has no effect", fs.increment.toChars()); + deprecation(fs.increment.loc, "`%s` has no effect", fs.increment.toErrMsg()); if (checkNonAssignmentArrayOp(fs.increment)) fs.increment = ErrorExp.get(); fs.increment = fs.increment.optimize(WANTvalue); @@ -2604,7 +2604,7 @@ Statement statementSemanticVisit(Statement s, Scope* sc) //errors = true; } if (global.endGagging(olderrors)) - deprecation(rs.exp.loc, "`%s` has no effect", rs.exp.toChars()); + deprecation(rs.exp.loc, "`%s` has no effect", rs.exp.toErrMsg()); /* Replace: * return exp; diff --git a/gcc/d/dmd/tokens.d b/gcc/d/dmd/tokens.d index e82a582..aad88d6 100644 --- a/gcc/d/dmd/tokens.d +++ b/gcc/d/dmd/tokens.d @@ -436,8 +436,10 @@ enum FirstCKeyword = TOK.inline; // Assert that all token enum members have consecutive values and // that none of them overlap static assert(() { - foreach (idx, enumName; __traits(allMembers, TOK)) { - static if (idx != __traits(getMember, TOK, enumName)) { + foreach (idx, enumName; __traits(allMembers, TOK)) + { + static if (idx != __traits(getMember, TOK, enumName)) + { pragma(msg, "Error: Expected TOK.", enumName, " to be ", idx, " but is ", __traits(getMember, TOK, enumName)); static assert(0); } @@ -925,13 +927,18 @@ nothrow: return 0; } - extern(D) void appendInterpolatedPart(const ref OutBuffer buf) { + extern(D) void appendInterpolatedPart(const ref OutBuffer buf) + { appendInterpolatedPart(cast(const(char)*)buf[].ptr, buf.length); } - extern(D) void appendInterpolatedPart(const(char)[] str) { + + extern(D) void appendInterpolatedPart(const(char)[] str) + { appendInterpolatedPart(str.ptr, str.length); } - extern(D) void appendInterpolatedPart(const(char)* ptr, size_t length) { + + extern(D) void appendInterpolatedPart(const(char)* ptr, size_t length) + { assert(value == TOK.interpolated); if (interpolatedSet is null) interpolatedSet = new InterpolatedSet; diff --git a/gcc/d/dmd/typesem.d b/gcc/d/dmd/typesem.d index ae52de5..7f87ac4 100644 --- a/gcc/d/dmd/typesem.d +++ b/gcc/d/dmd/typesem.d @@ -1187,7 +1187,7 @@ private const(char)* getParamError(TypeFunction tf, Expression arg, Parameter pa // 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, + rv ? "rvalue ".ptr : "".ptr, arg.toErrMsg(), at, parameterToChars(par, tf, qual)); return buf.extractChars(); } @@ -2329,7 +2329,7 @@ Type typeSemantic(Type type, Loc loc, Scope* sc) { const(char)* errTxt = fparam.storageClass & STC.ref_ ? "ref" : "out"; .error(e.loc, "expression `%s` of type `%s` is not implicitly convertible to type `%s %s` of parameter `%s`", - e.toChars(), e.type.toChars(), errTxt, fparam.type.toChars(), fparam.toChars()); + e.toErrMsg(), e.type.toChars(), errTxt, fparam.type.toChars(), fparam.toChars()); } e = e.implicitCastTo(sc, fparam.type); @@ -2493,10 +2493,17 @@ Type typeSemantic(Type type, Loc loc, Scope* sc) errors = true; } - const bool isTypesafeVariadic = i + 1 == dim && - tf.parameterList.varargs == VarArg.typesafe && - (t.isTypeDArray() || t.isTypeClass()); - if (isTypesafeVariadic) + const bool isTypesafeVariadic = i + 1 == dim && tf.parameterList.varargs == VarArg.typesafe; + const bool isStackAllocatedVariadic = isTypesafeVariadic && (t.isTypeDArray() || t.isTypeClass()); + + if (isTypesafeVariadic && t.isTypeClass()) + { + // Deprecated in 2.111, kept as a legacy feature for compatibility (currently no plan to turn it into an error) + .deprecation(loc, "typesafe variadic parameters with a `class` type (`%s %s...`) are deprecated", + t.isTypeClass().sym.ident.toChars(), fparam.toChars()); + } + + if (isStackAllocatedVariadic) { /* typesafe variadic arguments are constructed on the stack, so must be `scope` */ @@ -2518,7 +2525,7 @@ Type typeSemantic(Type type, Loc loc, Scope* sc) } } - if (isTypesafeVariadic) + if (isStackAllocatedVariadic) { /* This is because they can be constructed on the stack * https://dlang.org/spec/function.html#typesafe_variadic_functions @@ -3454,10 +3461,26 @@ Expression getProperty(Type t, Scope* scope_, Loc loc, Identifier ident, int fla { if (auto sym = dsym.isAggregateDeclaration()) { - if (auto fd = search_function(sym, Id.opDispatch)) - errorSupplemental(loc, "potentially malformed `opDispatch`. Use an explicit instantiation to get a better error message"); - else if (!sym.members) + if (!sym.members) + { errorSupplemental(sym.loc, "`%s %s` is opaque and has no members.", sym.kind, mt.toPrettyChars(true)); + return ErrorExp.get(); + } + + if (auto fd = search_function(sym, Id.opDispatch)) + { + if (auto td = fd.isTemplateDeclaration()) + { + e = mt.defaultInitLiteral(loc); + auto se = new StringExp(e.loc, ident.toString()); + auto tiargs = new Objects(); + tiargs.push(se); + auto dti = new DotTemplateInstanceExp(e.loc, e, Id.opDispatch, tiargs); + dti.ti.tempdecl = td; + dti.dotTemplateSemanticProp(scope_, DotExpFlag.none); + return ErrorExp.get(); + } + } } errorSupplemental(dsym.loc, "%s `%s` defined here", dsym.kind, dsym.toChars()); @@ -4731,7 +4754,7 @@ Expression dotExp(Type mt, Scope* sc, Expression e, Identifier ident, DotExpFlag { if (e.op == EXP.type) { - error(e.loc, "`%s` is not an expression", e.toChars()); + error(e.loc, "`%s` is not an expression", e.toErrMsg()); return ErrorExp.get(); } else if (mt.dim.toUInteger() < 1 && checkUnsafeDotExp(sc, e, ident, flag)) @@ -4780,7 +4803,7 @@ Expression dotExp(Type mt, Scope* sc, Expression e, Identifier ident, DotExpFlag } if (e.op == EXP.type && (ident == Id.length || ident == Id.ptr)) { - error(e.loc, "`%s` is not an expression", e.toChars()); + error(e.loc, "`%s` is not an expression", e.toErrMsg()); return ErrorExp.get(); } if (ident == Id.length) @@ -5207,7 +5230,7 @@ Expression dotExp(Type mt, Scope* sc, Expression e, Identifier ident, DotExpFlag Declaration d = s.isDeclaration(); if (!d) { - error(e.loc, "`%s.%s` is not a declaration", e.toChars(), ident.toChars()); + error(e.loc, "`%s.%s` is not a declaration", e.toErrMsg(), ident.toChars()); return ErrorExp.get(); } @@ -5640,7 +5663,7 @@ Expression dotExp(Type mt, Scope* sc, Expression e, Identifier ident, DotExpFlag Declaration d = s.isDeclaration(); if (!d) { - error(e.loc, "`%s.%s` is not a declaration", e.toChars(), ident.toChars()); + error(e.loc, "`%s.%s` is not a declaration", e.toErrMsg(), ident.toChars()); return ErrorExp.get(); } @@ -6715,30 +6738,32 @@ Type pointerTo(Type type) { if (type.ty == Terror) return type; - if (!type.pto) + auto mcache = type.getMcache(); + if (!mcache.pto) { Type t = new TypePointer(type); if (type.ty == Tfunction) { t.deco = t.merge().deco; - type.pto = t; + mcache.pto = t; } else - type.pto = t.merge(); + mcache.pto = t.merge(); } - return type.pto; + return mcache.pto; } Type referenceTo(Type type) { if (type.ty == Terror) return type; - if (!type.rto) + auto mcache = type.getMcache(); + if (!mcache.rto) { Type t = new TypeReference(type); - type.rto = t.merge(); + mcache.rto = t.merge(); } - return type.rto; + return mcache.rto; } // Make corresponding static array type without semantic @@ -6756,12 +6781,13 @@ Type arrayOf(Type type) { if (type.ty == Terror) return type; - if (!type.arrayof) + auto mcache = type.getMcache(); + if (!mcache.arrayof) { Type t = new TypeDArray(type); - type.arrayof = t.merge(); + mcache.arrayof = t.merge(); } - return type.arrayof; + return mcache.arrayof; } /******************************** @@ -7013,6 +7039,39 @@ Type sharedWildConstOf(Type type) return t; } +Type nakedOf(Type type) +{ + //printf("Type::nakedOf() %p, %s\n", type, type.toChars()); + if (type.mod == 0) + return type; + if (type.mcache) with(type.mcache) + { + // the cache has the naked type at the "identity" position, try to find it + if (cto && cto.mod == 0) + return cto; + if (ito && ito.mod == 0) + return ito; + if (sto && sto.mod == 0) + return sto; + if (scto && scto.mod == 0) + return scto; + if (wto && wto.mod == 0) + return wto; + if (wcto && wcto.mod == 0) + return wcto; + if (swto && swto.mod == 0) + return swto; + if (swcto && swcto.mod == 0) + return swcto; + } + Type t = type.nullAttributes(); + t.mod = 0; + t = t.merge(); + t.fixTo(type); + //printf("\t%p %s\n", t, t.toChars()); + return t; +} + Type unqualify(Type type, uint m) { Type t = type.mutableOf().unSharedOf(); diff --git a/gcc/d/dmd/typinf.d b/gcc/d/dmd/typinf.d index 58102cd..1a96823 100644 --- a/gcc/d/dmd/typinf.d +++ b/gcc/d/dmd/typinf.d @@ -22,6 +22,7 @@ import dmd.expression; import dmd.globals; import dmd.location; import dmd.mtype; +import dmd.typesem; import core.stdc.stdio; /**************************************************** @@ -67,6 +68,9 @@ bool genTypeInfo(Expression e, Loc loc, Type torig, Scope* sc) import dmd.typesem : merge2; Type t = torig.merge2(); // do this since not all Type's are merge'd + if (t.ty == Taarray) + t = makeNakedAssociativeArray(cast(TypeAArray)t); + bool needsCodegen = false; if (!t.vtinfo) { @@ -79,7 +83,7 @@ bool genTypeInfo(Expression e, Loc loc, Type torig, Scope* sc) else if (t.isWild()) t.vtinfo = TypeInfoWildDeclaration.create(t); else - t.vtinfo = getTypeInfoDeclaration(t); + t.vtinfo = getTypeInfoDeclaration(t, sc); assert(t.vtinfo); // ClassInfos are generated as part of ClassDeclaration codegen @@ -105,7 +109,7 @@ bool genTypeInfo(Expression e, Loc loc, Type torig, Scope* sc) */ extern (C++) Type getTypeInfoType(Loc loc, Type t, Scope* sc); -private TypeInfoDeclaration getTypeInfoDeclaration(Type t) +private TypeInfoDeclaration getTypeInfoDeclaration(Type t, Scope* sc) { //printf("Type::getTypeInfoDeclaration() %s\n", t.toChars()); switch (t.ty) @@ -117,7 +121,7 @@ private TypeInfoDeclaration getTypeInfoDeclaration(Type t) case Tsarray: return TypeInfoStaticArrayDeclaration.create(t); case Taarray: - return TypeInfoAssociativeArrayDeclaration.create(t); + return getTypeInfoAssocArrayDeclaration(cast(TypeAArray)t, sc); case Tstruct: return TypeInfoStructDeclaration.create(t); case Tvector: @@ -141,6 +145,70 @@ private TypeInfoDeclaration getTypeInfoDeclaration(Type t) } } +/****************************************** + * Instantiate TypeInfoAssociativeArrayDeclaration and fill + * the entry with TypeInfo_AssociativeArray.Entry!(t.index, t.next) + * + * Params: + * t = TypeAArray to generate TypeInfo_AssociativeArray for + * sc = context + * Returns: + * a TypeInfoAssociativeArrayDeclaration with field entry initialized + */ +TypeInfoDeclaration getTypeInfoAssocArrayDeclaration(TypeAArray t, Scope* sc) +{ + import dmd.arraytypes; + import dmd.expressionsem; + import dmd.id; + + assert(sc); // must not be called in the code generation phase + + auto ti = TypeInfoAssociativeArrayDeclaration.create(t); + t.vtinfo = ti; // assign it early to avoid recursion in expressionSemantic + Loc loc = t.loc; + auto tiargs = new Objects(); + tiargs.push(t.index); // always called with naked types + tiargs.push(t.next); + + Expression id = new IdentifierExp(loc, Id.empty); + id = new DotIdExp(loc, id, Id.object); + id = new DotIdExp(loc, id, Id.TypeInfo_AssociativeArray); + auto tempinst = new DotTemplateInstanceExp(loc, id, Id.Entry, tiargs); + auto e = expressionSemantic(tempinst, sc); + assert(e.type); + ti.entry = e.type; + if (auto ts = ti.entry.isTypeStruct()) + { + ts.sym.requestTypeInfo = true; + if (auto tmpl = ts.sym.isInstantiated()) + tmpl.minst = sc._module.importedFrom; // ensure it get's emitted + } + getTypeInfoType(loc, ti.entry, sc); + assert(ti.entry.vtinfo); + + return ti; +} + +/****************************************** + * Find or create a TypeAArray with index and next without + * any head modifiers, tail `inout` is replaced with `const` + * + * Params: + * t = TypeAArray to convert + * Returns: + * t = found type + */ +Type makeNakedAssociativeArray(TypeAArray t) +{ + Type tindex = t.index.toBasetype().nakedOf().substWildTo(MODFlags.const_); + Type tnext = t.next.toBasetype().nakedOf().substWildTo(MODFlags.const_); + if (tindex == t.index && tnext == t.next) + return t; + + t = new TypeAArray(tnext, tindex); + return t.merge(); +} + /************************************************** * Returns: * true if any part of type t is speculative. diff --git a/gcc/d/dmd/typinf.h b/gcc/d/dmd/typinf.h index 4a8c942..e416191 100644 --- a/gcc/d/dmd/typinf.h +++ b/gcc/d/dmd/typinf.h @@ -14,6 +14,8 @@ class Expression; class Type; +class TypeAArray; +class TypeInfoDeclaration; struct Scope; namespace dmd @@ -21,5 +23,7 @@ namespace dmd bool genTypeInfo(Expression *e, Loc loc, Type *torig, Scope *sc); bool isSpeculativeType(Type *t); bool builtinTypeInfo(Type *t); + Type *makeNakedAssociativeArray(TypeAArray *t); + TypeInfoDeclaration *getTypeInfoAssocArrayDeclaration(TypeAArray *t, Scope *sc); } Type *getTypeInfoType(Loc loc, Type *t, Scope *sc); |