aboutsummaryrefslogtreecommitdiff
path: root/gcc/d
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/d')
-rw-r--r--gcc/d/dmd/MERGE2
-rw-r--r--gcc/d/dmd/VERSION2
-rw-r--r--gcc/d/dmd/aggregate.d2
-rw-r--r--gcc/d/dmd/aggregate.h2
-rw-r--r--gcc/d/dmd/astenums.d1
-rw-r--r--gcc/d/dmd/attrib.d111
-rw-r--r--gcc/d/dmd/attrib.h7
-rw-r--r--gcc/d/dmd/common/outbuffer.d6
-rw-r--r--gcc/d/dmd/cparse.d7
-rw-r--r--gcc/d/dmd/ctfeexpr.d55
-rw-r--r--gcc/d/dmd/dcast.d7
-rw-r--r--gcc/d/dmd/dclass.d67
-rw-r--r--gcc/d/dmd/declaration.d12
-rw-r--r--gcc/d/dmd/declaration.h1
-rw-r--r--gcc/d/dmd/denum.d32
-rw-r--r--gcc/d/dmd/dimport.d40
-rw-r--r--gcc/d/dmd/dmodule.d65
-rw-r--r--gcc/d/dmd/dscope.d22
-rw-r--r--gcc/d/dmd/dstruct.d17
-rw-r--r--gcc/d/dmd/dsymbol.d475
-rw-r--r--gcc/d/dmd/dsymbol.h16
-rw-r--r--gcc/d/dmd/dsymbolsem.d986
-rw-r--r--gcc/d/dmd/dtemplate.d7
-rw-r--r--gcc/d/dmd/dtoh.d1
-rw-r--r--gcc/d/dmd/dversion.d75
-rw-r--r--gcc/d/dmd/enum.h2
-rw-r--r--gcc/d/dmd/escape.d22
-rw-r--r--gcc/d/dmd/expression.d4
-rw-r--r--gcc/d/dmd/expression.h4
-rw-r--r--gcc/d/dmd/expressionsem.d160
-rw-r--r--gcc/d/dmd/func.d61
-rw-r--r--gcc/d/dmd/hdrgen.d21
-rw-r--r--gcc/d/dmd/id.d3
-rw-r--r--gcc/d/dmd/import.h2
-rw-r--r--gcc/d/dmd/importc.d1
-rw-r--r--gcc/d/dmd/init.d29
-rw-r--r--gcc/d/dmd/init.h10
-rw-r--r--gcc/d/dmd/initsem.d19
-rw-r--r--gcc/d/dmd/lambdacomp.d1
-rw-r--r--gcc/d/dmd/module.h2
-rw-r--r--gcc/d/dmd/nogc.d16
-rw-r--r--gcc/d/dmd/nspace.d43
-rw-r--r--gcc/d/dmd/nspace.h2
-rw-r--r--gcc/d/dmd/opover.d1
-rw-r--r--gcc/d/dmd/optimize.d12
-rw-r--r--gcc/d/dmd/parse.d67
-rw-r--r--gcc/d/dmd/parsetimevisitor.d1
-rw-r--r--gcc/d/dmd/scope.h5
-rw-r--r--gcc/d/dmd/semantic3.d2
-rw-r--r--gcc/d/dmd/statementsem.d4
-rw-r--r--gcc/d/dmd/staticassert.d5
-rw-r--r--gcc/d/dmd/staticassert.h1
-rw-r--r--gcc/d/dmd/traits.d82
-rw-r--r--gcc/d/dmd/typesem.d2
-rw-r--r--gcc/d/dmd/version.h2
-rw-r--r--gcc/d/dmd/visitor.h2
-rw-r--r--gcc/d/expr.cc99
-rw-r--r--gcc/d/runtime.def7
58 files changed, 1447 insertions, 1265 deletions
diff --git a/gcc/d/dmd/MERGE b/gcc/d/dmd/MERGE
index 0cf9b5f..aa0062c 100644
--- a/gcc/d/dmd/MERGE
+++ b/gcc/d/dmd/MERGE
@@ -1,4 +1,4 @@
-65a3da148c0c700a6c928f0e13799b2a7d34fcbe
+ff57fec51558013b25cadb7e83da9f4675915d56
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/VERSION b/gcc/d/dmd/VERSION
index b272d4b..41fdc65 100644
--- a/gcc/d/dmd/VERSION
+++ b/gcc/d/dmd/VERSION
@@ -1 +1 @@
-v2.106.0-beta.1
+v2.106.0-rc.1
diff --git a/gcc/d/dmd/aggregate.d b/gcc/d/dmd/aggregate.d
index d42ef951..307bb01 100644
--- a/gcc/d/dmd/aggregate.d
+++ b/gcc/d/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/gcc/d/dmd/aggregate.h b/gcc/d/dmd/aggregate.h
index 58a0126..cd8f1a1 100644
--- a/gcc/d/dmd/aggregate.h
+++ b/gcc/d/dmd/aggregate.h
@@ -167,7 +167,6 @@ private:
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 @@ public:
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/gcc/d/dmd/astenums.d b/gcc/d/dmd/astenums.d
index 77f36f3..6a9c010 100644
--- a/gcc/d/dmd/astenums.d
+++ b/gcc/d/dmd/astenums.d
@@ -383,6 +383,7 @@ enum STMT : ubyte
enum InitKind : ubyte
{
void_,
+ default_,
error,
struct_,
array,
diff --git a/gcc/d/dmd/attrib.d b/gcc/d/dmd/attrib.d
index 49fc308..251e2e8 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 : 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/gcc/d/dmd/attrib.h b/gcc/d/dmd/attrib.h
index f47a1f6..efea9af 100644
--- a/gcc/d/dmd/attrib.h
+++ b/gcc/d/dmd/attrib.h
@@ -26,7 +26,6 @@ public:
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 @@ public:
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 @@ public:
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 @@ public:
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 @@ public:
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 @@ public:
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 @@ public:
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/gcc/d/dmd/common/outbuffer.d b/gcc/d/dmd/common/outbuffer.d
index b8ad785..4e7a82f 100644
--- a/gcc/d/dmd/common/outbuffer.d
+++ b/gcc/d/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/gcc/d/dmd/cparse.d b/gcc/d/dmd/cparse.d
index f0c8349..ed5f1f8 100644
--- a/gcc/d/dmd/cparse.d
+++ b/gcc/d/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/gcc/d/dmd/ctfeexpr.d b/gcc/d/dmd/ctfeexpr.d
index c93269f..43efc05 100644
--- a/gcc/d/dmd/ctfeexpr.d
+++ b/gcc/d/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;
@@ -43,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;
}
@@ -109,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);
}
@@ -134,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)
{
@@ -145,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);
}
@@ -153,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 (;;)
@@ -593,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));
@@ -741,14 +742,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 +795,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 +837,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),
@@ -978,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)
{
@@ -997,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
@@ -1105,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())
@@ -1116,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_;
}
@@ -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_)
@@ -2000,9 +1999,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 +2017,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)
{
diff --git a/gcc/d/dmd/dcast.d b/gcc/d/dmd/dcast.d
index eb3890b..14c67f0 100644
--- a/gcc/d/dmd/dcast.d
+++ b/gcc/d/dmd/dcast.d
@@ -1631,6 +1631,13 @@ Expression castTo(Expression e, Scope* sc, Type t, Type att = null)
}
else if (tob.ty == Tvector && t1b.ty != Tvector)
{
+ if (t1b.ty == Tsarray)
+ {
+ // Casting static array to vector with same size, e.g. `cast(int4) int[4]`
+ if (t1b.size(e.loc) != tob.size(e.loc))
+ goto Lfail;
+ return new VectorExp(e.loc, e, tob).expressionSemantic(sc);
+ }
//printf("test1 e = %s, e.type = %s, tob = %s\n", e.toChars(), e.type.toChars(), tob.toChars());
TypeVector tv = tob.isTypeVector();
Expression result = new CastExp(e.loc, e, tv.elementType());
diff --git a/gcc/d/dmd/dclass.d b/gcc/d/dmd/dclass.d
index bae942c..72b85cf 100644
--- a/gcc/d/dmd/dclass.d
+++ b/gcc/d/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/gcc/d/dmd/declaration.d b/gcc/d/dmd/declaration.d
index 76a31f4..0e125fd 100644
--- a/gcc/d/dmd/declaration.d
+++ b/gcc/d/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/gcc/d/dmd/declaration.h b/gcc/d/dmd/declaration.h
index 8cd295f..a65fb44 100644
--- a/gcc/d/dmd/declaration.h
+++ b/gcc/d/dmd/declaration.h
@@ -124,7 +124,6 @@ public:
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/gcc/d/dmd/denum.d b/gcc/d/dmd/denum.d
index f33b5fd..797f6ee 100644
--- a/gcc/d/dmd/denum.d
+++ b/gcc/d/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)
@@ -126,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/gcc/d/dmd/dimport.d b/gcc/d/dmd/dimport.d
index d74c860..0132e49 100644
--- a/gcc/d/dmd/dimport.d
+++ b/gcc/d/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);
@@ -348,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/gcc/d/dmd/dmodule.d b/gcc/d/dmd/dmodule.d
index e6dde18..5f5de63 100644
--- a/gcc/d/dmd/dmodule.d
+++ b/gcc/d/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/gcc/d/dmd/dscope.d b/gcc/d/dmd/dscope.d
index 3853512..d68bcda 100644
--- a/gcc/d/dmd/dscope.d
+++ b/gcc/d/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
@@ -344,7 +350,7 @@ extern (C++) struct Scope
* Returns:
* symbol if found, null if not
*/
- extern (D) Dsymbol search(const ref Loc loc, Identifier ident, Dsymbol* pscopesym, int flags = IgnoreNone)
+ extern (C++) Dsymbol search(const ref Loc loc, Identifier ident, Dsymbol* pscopesym, int flags = IgnoreNone)
{
version (LOGSEARCH)
{
@@ -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/gcc/d/dmd/dstruct.d b/gcc/d/dmd/dstruct.d
index f77a263..36e847c 100644
--- a/gcc/d/dmd/dstruct.d
+++ b/gcc/d/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/gcc/d/dmd/dsymbol.d b/gcc/d/dmd/dsymbol.d
index 914213c..a52745f 100644
--- a/gcc/d/dmd/dsymbol.d
+++ b/gcc/d/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;
@@ -750,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.
@@ -831,21 +769,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)
{
/***************************************************
@@ -870,7 +793,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());
}
@@ -1339,12 +1262,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
@@ -1373,166 +1296,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)
{
@@ -1844,40 +1608,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;
@@ -1896,217 +1626,28 @@ 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;
+ RootObject arrayContent;
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;
}
- /// 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(sc);
- return v;
- case type:
- return dollarFromTypeTuple(loc, cast(TypeTuple) arrayContent, sc);
- 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, sc);
- }
- /* *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(sc);
- 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(sc);
- 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(sc);
- return (*pvar);
- }
-
override inout(ArrayScopeSymbol) isArrayScopeSymbol() inout
{
return this;
diff --git a/gcc/d/dmd/dsymbol.h b/gcc/d/dmd/dsymbol.h
index 0278975..e0c2046 100644
--- a/gcc/d/dmd/dsymbol.h
+++ b/gcc/d/dmd/dsymbol.h
@@ -228,10 +228,8 @@ public:
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);
virtual bool overloadInsert(Dsymbol *s);
virtual uinteger_t size(const Loc &loc);
virtual bool isforwardRef();
@@ -331,16 +329,14 @@ public:
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;
@@ -362,7 +358,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); }
@@ -372,12 +367,8 @@ public:
class ArrayScopeSymbol final : public ScopeDsymbol
{
-private:
- RootObject *arrayContent;
public:
- Scope *sc;
-
- 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); }
@@ -437,3 +428,6 @@ public:
// Number of symbols in symbol table
size_t length() const;
};
+
+void addMember(Dsymbol *dsym, Scope *sc, ScopeDsymbol *sds);
+Dsymbol *search(Dsymbol *d, const Loc &loc, Identifier *ident, int flags = SearchLocalsOnly);
diff --git a/gcc/d/dmd/dsymbolsem.d b/gcc/d/dmd/dsymbolsem.d
index 637edd7..430377f 100644
--- a/gcc/d/dmd/dsymbolsem.d
+++ b/gcc/d/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;
@@ -1141,7 +1142,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;
}
@@ -1170,10 +1171,12 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
// https://issues.dlang.org/show_bug.cgi?id=14166
// Don't run CTFE for the temporary variables inside typeof
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();
if (init_err && init_err.exp.op == EXP.showCtfeContext)
{
- errorSupplemental(dsym.loc, "compile time context created here");
+ errorSupplemental(dsym.loc, "compile time context created here");
}
}
}
@@ -1979,7 +1982,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)
@@ -3385,7 +3388,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)
@@ -5831,6 +5834,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:
@@ -5904,7 +6266,7 @@ private bool isDRuntimeHook(Identifier id)
id == Id._d_arraysetlengthTImpl || id == Id._d_arraysetlengthT ||
id == Id._d_arraysetlengthTTrace ||
id == Id._d_arrayappendT || id == Id._d_arrayappendTTrace ||
- id == Id._d_arrayappendcTXImpl;
+ id == Id._d_arrayappendcTX;
}
void templateInstanceSemantic(TemplateInstance tempinst, Scope* sc, ArgumentList argumentList)
@@ -7431,3 +7793,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/gcc/d/dmd/dtemplate.d b/gcc/d/dmd/dtemplate.d
index 4cf1bae..037e0d0 100644
--- a/gcc/d/dmd/dtemplate.d
+++ b/gcc/d/dmd/dtemplate.d
@@ -746,7 +746,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)
{
@@ -763,6 +763,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);
+ }
}
}
diff --git a/gcc/d/dmd/dtoh.d b/gcc/d/dmd/dtoh.d
index 7c76da9..9f85574 100644
--- a/gcc/d/dmd/dtoh.d
+++ b/gcc/d/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/gcc/d/dmd/dversion.d b/gcc/d/dmd/dversion.d
index aa22532..31725c8 100644
--- a/gcc/d/dmd/dversion.d
+++ b/gcc/d/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/gcc/d/dmd/enum.h b/gcc/d/dmd/enum.h
index be12c65..e17e8cf 100644
--- a/gcc/d/dmd/enum.h
+++ b/gcc/d/dmd/enum.h
@@ -46,12 +46,10 @@ public:
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;
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/gcc/d/dmd/escape.d b/gcc/d/dmd/escape.d
index 3f85ea0..e25fc84 100644
--- a/gcc/d/dmd/escape.d
+++ b/gcc/d/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/gcc/d/dmd/expression.d b/gcc/d/dmd/expression.d
index 4790221..cd93e54 100644
--- a/gcc/d/dmd/expression.d
+++ b/gcc/d/dmd/expression.d
@@ -4617,7 +4617,9 @@ extern (C++) final class UshrAssignExp : BinAssignExp
*/
extern (C++) class CatAssignExp : BinAssignExp
{
- extern (D) this(const ref Loc loc, Expression e1, Expression e2) @safe
+ Expression lowering; // lowered druntime hook `_d_arrayappend{cTX,T}`
+
+ extern (D) this(const ref Loc loc, Expression e1, Expression e2)
{
super(loc, EXP.concatenateAssign, e1, e2);
}
diff --git a/gcc/d/dmd/expression.h b/gcc/d/dmd/expression.h
index 12ca6b4..b4ace74b 100644
--- a/gcc/d/dmd/expression.h
+++ b/gcc/d/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);
typedef unsigned char OwnedBy;
@@ -1114,6 +1114,8 @@ public:
class CatAssignExp : public BinAssignExp
{
public:
+ Expression *lowering; // lowered druntime hook `_d_arrayappend{cTX,T}`
+
void accept(Visitor *v) override { v->visit(this); }
};
diff --git a/gcc/d/dmd/expressionsem.d b/gcc/d/dmd/expressionsem.d
index d55ab3b..e6b9018 100644
--- a/gcc/d/dmd/expressionsem.d
+++ b/gcc/d/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())
@@ -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())
{
@@ -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.
@@ -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;
@@ -5166,6 +5166,45 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
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);
+ }
}
else if (tb.isscalar())
{
@@ -8295,7 +8334,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 +8424,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;
@@ -9017,14 +9056,6 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
return setError();
}
- // Look for casting to a vector type
- if (tob.ty == Tvector && t1b.ty != Tvector)
- {
- result = new VectorExp(exp.loc, exp.e1, exp.to);
- result = result.expressionSemantic(sc);
- return;
- }
-
Expression ex = exp.e1.castTo(sc, exp.to);
if (ex.op == EXP.error)
{
@@ -11727,8 +11758,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
result = res;
- if ((exp.op == EXP.concatenateAssign || exp.op == EXP.concatenateElemAssign) &&
- sc.needsCodegen())
+ if ((exp.op == EXP.concatenateAssign || exp.op == EXP.concatenateElemAssign) && sc.needsCodegen())
{
// if aa ordering is triggered, `res` will be a CommaExp
// and `.e2` will be the rewritten original expression.
@@ -11772,7 +11802,9 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
arguments.push(exp.e1);
arguments.push(exp.e2);
Expression ce = new CallExp(exp.loc, id, arguments);
- *output = ce.expressionSemantic(sc);
+
+ exp.lowering = ce.expressionSemantic(sc);
+ *output = exp;
}
else if (exp.op == EXP.concatenateElemAssign)
{
@@ -11792,15 +11824,12 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
}
Identifier hook = global.params.tracegc ? Id._d_arrayappendcTXTrace : Id._d_arrayappendcTX;
- if (!verifyHookExist(exp.loc, *sc, Id._d_arrayappendcTXImpl, "appending element to arrays", Id.object))
+ if (!verifyHookExist(exp.loc, *sc, hook, "appending element to arrays", Id.object))
return setError();
- // Lower to object._d_arrayappendcTXImpl!(typeof(e1))._d_arrayappendcTX{,Trace}(e1, 1), e1[$-1]=e2
+ // Lower to object._d_arrayappendcTX{,Trace}(e1, 1), e1[$-1]=e2
Expression id = new IdentifierExp(exp.loc, Id.empty);
id = new DotIdExp(exp.loc, id, Id.object);
- auto tiargs = new Objects();
- tiargs.push(exp.e1.type);
- id = new DotTemplateInstanceExp(exp.loc, id, Id._d_arrayappendcTXImpl, tiargs);
id = new DotIdExp(exp.loc, id, hook);
auto arguments = new Expressions();
@@ -11827,11 +11856,10 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
{
/* Before the template hook, this check was performed in e2ir.d
* for expressions like `a ~= a[$-1]`. Here, $ will be modified
- * by calling `_d_arrayappendcT`, so we need to save `a[$-1]` in
+ * by calling `_d_arrayappendcTX`, so we need to save `a[$-1]` in
* a temporary variable.
*/
value2 = extractSideEffect(sc, "__appendtmp", eValue2, value2, true);
- exp.e2 = value2;
// `__appendtmp*` will be destroyed together with the array `exp.e1`.
auto vd = eValue2.isDeclarationExp().declaration.isVarDeclaration();
@@ -11847,13 +11875,12 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
auto e0 = Expression.combine(ce, ae).expressionSemantic(sc);
e0 = Expression.combine(e0, value1);
e0 = Expression.combine(eValue1, e0);
-
e0 = Expression.combine(eValue2, e0);
- *output = e0.expressionSemantic(sc);
+ exp.lowering = e0.expressionSemantic(sc);
+ *output = exp;
}
}
-
}
override void visit(AddExp exp)
@@ -15210,15 +15237,21 @@ 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";
+
+ assert(e);
Expression visit(Expression _this)
{
// BinaryAssignExp does not have an EXP associated
@@ -15230,9 +15263,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 +15276,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 +15320,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 +15405,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 +15424,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 +15465,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);
@@ -15634,12 +15669,13 @@ 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());
// 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)
@@ -15672,7 +15708,7 @@ private Expression modifiableLvalueImpl(Expression _this, Scope* sc, Expression
return ErrorExp.get();
}
}
- return exp.toLvalueImpl(sc, e);
+ return exp.toLvalueImpl(sc, "modify", e);
}
Expression visitString(StringExp exp)
@@ -15762,7 +15798,7 @@ private Expression modifiableLvalueImpl(Expression _this, Scope* sc, Expression
}
exp.e1 = exp.e1.modifiableLvalue(sc);
exp.e2 = exp.e2.modifiableLvalue(sc);
- return exp.toLvalue(sc);
+ return exp.toLvalue(sc, "modify");
}
switch(_this.op)
@@ -15803,7 +15839,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/gcc/d/dmd/func.d b/gcc/d/dmd/func.d
index edf113e..351faa47 100644
--- a/gcc/d/dmd/func.d
+++ b/gcc/d/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;
}
@@ -3422,15 +3412,25 @@ 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);
auto mismatches = MODMatchToBuffer(&funcBuf, tf.mod, tthis.mod);
if (hasOverloads)
{
- .error(loc, "none of the overloads of `%s` are callable using a %sobject",
- fd.ident.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 with argument types `(%s)`",
+ fd.toChars(), thisBuf.peekChars(), buf.peekChars());
+
if (!global.gag || global.params.v.showGaggedErrors)
printCandidates(loc, fd, sc.isDeprecated());
return null;
@@ -3447,8 +3447,12 @@ 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.toPrettyChars(), thisBuf.peekChars());
+ else
+ .error(loc, "%smethod `%s` is not callable using a %sobject",
+ funcBuf.peekChars(), fd.toPrettyChars(), thisBuf.peekChars());
if (mismatches.isNotShared)
.errorSupplemental(fd.loc, "Consider adding `shared` here");
@@ -3535,11 +3539,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())
{
@@ -4621,7 +4631,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/gcc/d/dmd/hdrgen.d b/gcc/d/dmd/hdrgen.d
index 8325081..ac2dda3 100644
--- a/gcc/d/dmd/hdrgen.d
+++ b/gcc/d/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(')');
}
@@ -3862,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/gcc/d/dmd/id.d b/gcc/d/dmd/id.d
index 5fcda91..32221d9 100644
--- a/gcc/d/dmd/id.d
+++ b/gcc/d/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" },
@@ -366,7 +368,6 @@ immutable Msgtable[] msgtable =
{ "_d_arraysetlengthTTrace"},
{ "_d_arrayappendT" },
{ "_d_arrayappendTTrace" },
- { "_d_arrayappendcTXImpl" },
{ "_d_arrayappendcTX" },
{ "_d_arrayappendcTXTrace" },
{ "_d_arraycatnTX" },
diff --git a/gcc/d/dmd/import.h b/gcc/d/dmd/import.h
index 31ee61a..aeb3621 100644
--- a/gcc/d/dmd/import.h
+++ b/gcc/d/dmd/import.h
@@ -43,9 +43,7 @@ public:
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;
Import *isImport() override { return this; }
diff --git a/gcc/d/dmd/importc.d b/gcc/d/dmd/importc.d
index 98ac903..2c7699b 100644
--- a/gcc/d/dmd/importc.d
+++ b/gcc/d/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/gcc/d/dmd/init.d b/gcc/d/dmd/init.d
index ebcd011..e484100 100644
--- a/gcc/d/dmd/init.d
+++ b/gcc/d/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;
@@ -112,6 +117,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/gcc/d/dmd/init.h b/gcc/d/dmd/init.h
index 67d0527..21bd07f 100644
--- a/gcc/d/dmd/init.h
+++ b/gcc/d/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 @@ public:
ErrorInitializer *isErrorInitializer();
VoidInitializer *isVoidInitializer();
+ DefaultInitializer *isDefaultInitializer();
StructInitializer *isStructInitializer();
ArrayInitializer *isArrayInitializer();
ExpInitializer *isExpInitializer();
@@ -53,6 +55,14 @@ public:
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/gcc/d/dmd/initsem.d b/gcc/d/dmd/initsem.d
index 139db0f..76c2d89 100644
--- a/gcc/d/dmd/initsem.d
+++ b/gcc/d/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;
@@ -106,6 +107,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 +121,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 +1025,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 +1189,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/gcc/d/dmd/lambdacomp.d b/gcc/d/dmd/lambdacomp.d
index ec070d8..d19d435 100644
--- a/gcc/d/dmd/lambdacomp.d
+++ b/gcc/d/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/gcc/d/dmd/module.h b/gcc/d/dmd/module.h
index 6e8153d..92efc16 100644
--- a/gcc/d/dmd/module.h
+++ b/gcc/d/dmd/module.h
@@ -43,7 +43,6 @@ public:
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 @@ public:
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/gcc/d/dmd/nogc.d b/gcc/d/dmd/nogc.d
index 59bf1d5..e59b010 100644
--- a/gcc/d/dmd/nogc.d
+++ b/gcc/d/dmd/nogc.d
@@ -108,12 +108,6 @@ public:
return;
f.printGCUsage(e.loc, "setting `length` may cause a GC allocation");
}
- else if (fd.ident == Id._d_arrayappendT || fd.ident == Id._d_arrayappendcTX)
- {
- if (setGC(e, "cannot use operator `~=` in `@nogc` %s `%s`"))
- return;
- f.printGCUsage(e.loc, "operator `~=` may cause a GC allocation");
- }
}
override void visit(ArrayLiteralExp e)
@@ -187,20 +181,14 @@ public:
override void visit(CatAssignExp e)
{
- /* CatAssignExp will exist in `__traits(compiles, ...)` and in the `.e1` branch of a `__ctfe ? :` CondExp.
- * The other branch will be `_d_arrayappendcTX(e1, 1), e1[$-1]=e2` which will generate the warning about
- * GC usage. See visit(CallExp).
- */
if (checkOnly)
{
err = true;
return;
}
- if (f.setGC(e.loc, null))
- {
- err = true;
+ if (setGC(e, "cannot use operator `~=` in `@nogc` %s `%s`"))
return;
- }
+ f.printGCUsage(e.loc, "operator `~=` may cause a GC allocation");
}
override void visit(CatExp e)
diff --git a/gcc/d/dmd/nspace.d b/gcc/d/dmd/nspace.d
index 2d3367a..a49e0bf 100644
--- a/gcc/d/dmd/nspace.d
+++ b/gcc/d/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);
@@ -126,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/gcc/d/dmd/nspace.h b/gcc/d/dmd/nspace.h
index e9fb7bd..7d30402 100644
--- a/gcc/d/dmd/nspace.h
+++ b/gcc/d/dmd/nspace.h
@@ -21,9 +21,7 @@ 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;
void setFieldOffset(AggregateDeclaration *ad, FieldState& fieldState, bool isunion) override;
const char *kind() const override;
diff --git a/gcc/d/dmd/opover.d b/gcc/d/dmd/opover.d
index b445b7b..b7bc925 100644
--- a/gcc/d/dmd/opover.d
+++ b/gcc/d/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/gcc/d/dmd/optimize.d b/gcc/d/dmd/optimize.d
index 69028fa..a979168 100644
--- a/gcc/d/dmd/optimize.d
+++ b/gcc/d/dmd/optimize.d
@@ -928,6 +928,14 @@ Expression optimize(Expression e, int result, bool keepLvalue = false)
}
}
+ void visitCatAssign(CatAssignExp e)
+ {
+ if (auto lowering = e.lowering)
+ optimize(lowering, result, keepLvalue);
+ else
+ visitBinAssign(e);
+ }
+
void visitBin(BinExp e)
{
//printf("BinExp::optimize(result = %d) %s\n", result, e.toChars());
@@ -1392,9 +1400,9 @@ Expression optimize(Expression e, int result, bool keepLvalue = false)
case EXP.leftShiftAssign:
case EXP.rightShiftAssign:
case EXP.unsignedRightShiftAssign:
+ case EXP.concatenateDcharAssign: visitBinAssign(ex.isBinAssignExp()); break;
case EXP.concatenateElemAssign:
- case EXP.concatenateDcharAssign:
- case EXP.concatenateAssign: visitBinAssign(ex.isBinAssignExp()); break;
+ case EXP.concatenateAssign: visitCatAssign(cast(CatAssignExp) ex); break;
case EXP.minusMinus:
case EXP.plusPlus:
diff --git a/gcc/d/dmd/parse.d b/gcc/d/dmd/parse.d
index 51e522d..f9d174a 100644
--- a/gcc/d/dmd/parse.d
+++ b/gcc/d/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/gcc/d/dmd/parsetimevisitor.d b/gcc/d/dmd/parsetimevisitor.d
index a4a9434..3d0a585 100644
--- a/gcc/d/dmd/parsetimevisitor.d
+++ b/gcc/d/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/gcc/d/dmd/scope.h b/gcc/d/dmd/scope.h
index 178542e..2cac5f2 100644
--- a/gcc/d/dmd/scope.h
+++ b/gcc/d/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
@@ -126,4 +129,6 @@ 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);
};
diff --git a/gcc/d/dmd/semantic3.d b/gcc/d/dmd/semantic3.d
index bf220f3..c255701 100644
--- a/gcc/d/dmd/semantic3.d
+++ b/gcc/d/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/gcc/d/dmd/statementsem.d b/gcc/d/dmd/statementsem.d
index f8b2c26..3873adc 100644
--- a/gcc/d/dmd/statementsem.d
+++ b/gcc/d/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/gcc/d/dmd/staticassert.d b/gcc/d/dmd/staticassert.d
index 15c46b3..7f22c4c 100644
--- a/gcc/d/dmd/staticassert.d
+++ b/gcc/d/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/gcc/d/dmd/staticassert.h b/gcc/d/dmd/staticassert.h
index 2b7d300..c0d5363 100644
--- a/gcc/d/dmd/staticassert.h
+++ b/gcc/d/dmd/staticassert.h
@@ -21,7 +21,6 @@ public:
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/gcc/d/dmd/traits.d b/gcc/d/dmd/traits.d
index 79df7fd..0acadbb 100644
--- a/gcc/d/dmd/traits.d
+++ b/gcc/d/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,43 +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;
- if (t.ty == Tclass && !(cast(TypeClass)t).sym.isInterfaceDeclaration())
- sz = (cast(TypeClass)t).sym.AggregateDeclaration.size(loc);
- else
- sz = t.size(loc);
+ auto tc = t.isTypeClass();
+ 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)
@@ -247,7 +255,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 +272,7 @@ ulong getTypePointerBitmap(Loc loc, Type t, Array!(ulong)* data)
offset = classoff;
}
- visitTopLevelClass(tc);
+ visitTopLevelClass(tcx);
}
else
visit(t);
@@ -281,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);
@@ -472,13 +480,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 +516,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 +538,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 +803,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 +1307,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 +1748,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);
@@ -1868,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)
{
diff --git a/gcc/d/dmd/typesem.d b/gcc/d/dmd/typesem.d
index 4a4c5d4..8795002 100644
--- a/gcc/d/dmd/typesem.d
+++ b/gcc/d/dmd/typesem.d
@@ -1099,7 +1099,7 @@ extern(C++) Type typeSemantic(Type type, const ref Loc loc, Scope* sc)
if (isRefOrOut && !isAuto &&
!(global.params.previewIn && (fparam.storageClass & STC.in_)) &&
global.params.rvalueRefParam != FeatureState.enabled)
- e = e.toLvalue(sc);
+ e = e.toLvalue(sc, "create default argument for `ref` / `out` parameter from");
fparam.defaultArg = e;
return (e.op != EXP.error);
diff --git a/gcc/d/dmd/version.h b/gcc/d/dmd/version.h
index 697d46e..c268bc9 100644
--- a/gcc/d/dmd/version.h
+++ b/gcc/d/dmd/version.h
@@ -20,7 +20,6 @@ public:
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 @@ public:
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); }
diff --git a/gcc/d/dmd/visitor.h b/gcc/d/dmd/visitor.h
index 3d8c3e6..360784a 100644
--- a/gcc/d/dmd/visitor.h
+++ b/gcc/d/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 @@ public:
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/gcc/d/expr.cc b/gcc/d/expr.cc
index 17801a3..a907979 100644
--- a/gcc/d/expr.cc
+++ b/gcc/d/expr.cc
@@ -789,42 +789,58 @@ public:
void visit (CatAssignExp *e) final override
{
+ if (!global.params.useGC)
+ {
+ error_at (make_location_t (e->loc),
+ "appending to array in %qs requires the GC and cannot be "
+ "used with %<-fno-druntime%>", e->toChars ());
+ this->result_ = error_mark_node;
+ return;
+ }
+
Type *tb1 = e->e1->type->toBasetype ();
Type *tb2 = e->e2->type->toBasetype ();
- Type *etype = tb1->nextOf ()->toBasetype ();
-
- /* Save the address of `e1', so it can be evaluated first.
- As all D run-time library functions for concat assignments update `e1'
- in-place and then return its value, the saved address can also be used as
- the result of this expression as well. */
- tree lhs = build_expr (e->e1);
- tree lexpr = stabilize_expr (&lhs);
- tree ptr = d_save_expr (build_address (lhs));
- tree result = NULL_TREE;
- if (tb1->ty == TY::Tarray && tb2->ty == TY::Tdchar
- && (etype->ty == TY::Tchar || etype->ty == TY::Twchar))
+ if (e->op == EXP::concatenateDcharAssign)
{
/* Append a dchar to a char[] or wchar[]:
The assignment is handled by the D run-time library, so only
need to call `_d_arrayappend[cw]d(&e1, e2)' */
+ Type *etype = tb1->nextOf ()->toBasetype ();
+
+ /* Save the address of `e1', so it can be evaluated first.
+ As all D run-time library functions for concat assignments update
+ `e1' in-place and then return its value, the saved address can also
+ be used as the result of this expression as well. */
+ tree lhs = build_expr (e->e1);
+ tree lexpr = stabilize_expr (&lhs);
+ tree ptr = d_save_expr (build_address (lhs));
+ tree result = NULL_TREE;
+
+ gcc_assert (tb1->ty == TY::Tarray && tb2->ty == TY::Tdchar
+ && (etype->ty == TY::Tchar || etype->ty == TY::Twchar));
+
libcall_fn libcall = (etype->ty == TY::Tchar)
? LIBCALL_ARRAYAPPENDCD : LIBCALL_ARRAYAPPENDWD;
result = build_libcall (libcall, e->type, 2,
ptr, build_expr (e->e2));
+
+ /* Construct in order: ptr = &e1, _d_arrayappend(ptr, e2), *ptr; */
+ result = compound_expr (compound_expr (lexpr, ptr), result);
+ this->result_ = compound_expr (result, build_deref (ptr));
}
else
{
+ gcc_assert (e->op == EXP::concatenateAssign
+ || e->op == EXP::concatenateElemAssign);
+ gcc_assert (tb1->ty == TY::Tarray || tb2->ty == TY::Tsarray);
/* Appending an element or array to another array has already been
handled by the front-end. */
- gcc_assert (tb1->ty == TY::Tarray || tb2->ty == TY::Tsarray);
- gcc_unreachable ();
- }
+ gcc_assert (e->lowering);
- /* Construct in order: ptr = &e1, _d_arrayappend(ptr, e2), *ptr; */
- result = compound_expr (compound_expr (lexpr, ptr), result);
- this->result_ = compound_expr (result, build_deref (ptr));
+ this->result_ = build_expr (e->lowering);
+ }
}
/* Build an assignment expression. The right operand is implicitly
@@ -2359,50 +2375,9 @@ public:
/* Allocating memory for a new D array. */
gcc_assert (e->arguments && e->arguments->length >= 1);
- if (e->arguments->length == 1)
- {
- /* Single dimension array allocations has already been handled by
- the front-end. */
- gcc_assert (e->lowering);
- result = build_expr (e->lowering);
- }
- else
- {
- /* Multidimensional array allocations. */
- tree tarray = make_array_type (Type::tsize_t, e->arguments->length);
- tree var = build_local_temp (tarray);
- vec <constructor_elt, va_gc> *elms = NULL;
-
- /* Get the base element type for the array, generating the
- initializer for the dims parameter along the way. */
- Type *telem = e->newtype->toBasetype ();
- for (size_t i = 0; i < e->arguments->length; i++)
- {
- Expression *arg = (*e->arguments)[i];
- CONSTRUCTOR_APPEND_ELT (elms, size_int (i), build_expr (arg));
-
- gcc_assert (telem->ty == TY::Tarray);
- telem = telem->toBasetype ()->nextOf ();
- gcc_assert (telem);
- }
-
- /* Initialize the temporary. */
- tree init = modify_expr (var, build_constructor (tarray, elms));
- var = compound_expr (init, var);
-
- /* Generate: _d_newarraymTX(ti, dims)
- or: _d_newarraymiTX(ti, dims) */
- libcall_fn libcall = telem->isZeroInit ()
- ? LIBCALL_NEWARRAYMTX : LIBCALL_NEWARRAYMITX;
-
- tree tinfo = build_typeinfo (e, e->type);
- tree dims = d_array_value (build_ctype (Type::tsize_t->arrayOf ()),
- size_int (e->arguments->length),
- build_address (var));
-
- result = build_libcall (libcall, e->newtype->toBasetype (), 2,
- tinfo, dims);
- }
+ /* Array allocations have already been handled by the front-end. */
+ gcc_assert (e->lowering != NULL);
+ result = build_expr (e->lowering);
if (e->argprefix)
result = compound_expr (build_expr (e->argprefix), result);
diff --git a/gcc/d/runtime.def b/gcc/d/runtime.def
index f7887e1..3307b3b 100644
--- a/gcc/d/runtime.def
+++ b/gcc/d/runtime.def
@@ -70,13 +70,6 @@ DEF_D_RUNTIME (DYNAMIC_CAST, "_d_dynamic_cast", RT(OBJECT),
DEF_D_RUNTIME (INTERFACE_CAST, "_d_interface_cast", RT(OBJECT),
P2(OBJECT, CLASSINFO), 0)
-/* Used when calling `new' on a multi-dimensional array.
- The `i' variant is for when the initializer is nonzero. */
-DEF_D_RUNTIME (NEWARRAYMTX, "_d_newarraymTX", RT(ARRAY_VOID),
- P2(CONST_TYPEINFO, ARRAY_SIZE_T), 0)
-DEF_D_RUNTIME (NEWARRAYMITX, "_d_newarraymiTX", RT(ARRAY_VOID),
- P2(CONST_TYPEINFO, ARRAY_SIZE_T), 0)
-
/* Used for allocating an array literal on the GC heap. */
DEF_D_RUNTIME (ARRAYLITERALTX, "_d_arrayliteralTX", RT(VOIDPTR),
P2(CONST_TYPEINFO, SIZE_T), 0)