mirror of
https://github.com/ldc-developers/ldc.git
synced 2025-05-07 19:36:06 +03:00

Notably, the glue layer side of the changed multiple interface inheritance layout (DMD a54e89d) has not been implemented yet. This corresponds to DMD commit 3f6a763c0589dd03c1c206eafd434b593702564e.
164 lines
4.5 KiB
D
164 lines
4.5 KiB
D
// Compiler implementation of the D programming language
|
|
// Copyright (c) 1999-2015 by Digital Mars
|
|
// All Rights Reserved
|
|
// written by Walter Bright
|
|
// http://www.digitalmars.com
|
|
// Distributed under the Boost Software License, Version 1.0.
|
|
// http://www.boost.org/LICENSE_1_0.txt
|
|
|
|
module ddmd.aliasthis;
|
|
|
|
import core.stdc.stdio;
|
|
import ddmd.aggregate;
|
|
import ddmd.declaration;
|
|
import ddmd.dscope;
|
|
import ddmd.dsymbol;
|
|
import ddmd.errors;
|
|
import ddmd.expression;
|
|
import ddmd.func;
|
|
import ddmd.globals;
|
|
import ddmd.hdrgen;
|
|
import ddmd.identifier;
|
|
import ddmd.mtype;
|
|
import ddmd.opover;
|
|
import ddmd.root.outbuffer;
|
|
import ddmd.tokens;
|
|
import ddmd.visitor;
|
|
|
|
/***********************************************************
|
|
* alias ident this;
|
|
*/
|
|
extern (C++) final class AliasThis : Dsymbol
|
|
{
|
|
public:
|
|
Identifier ident;
|
|
|
|
extern (D) this(Loc loc, Identifier ident)
|
|
{
|
|
super(null); // it's anonymous (no identifier)
|
|
this.loc = loc;
|
|
this.ident = ident;
|
|
}
|
|
|
|
override Dsymbol syntaxCopy(Dsymbol s)
|
|
{
|
|
assert(!s);
|
|
/* Since there is no semantic information stored here,
|
|
* we don't need to copy it.
|
|
*/
|
|
return this;
|
|
}
|
|
|
|
override void semantic(Scope* sc)
|
|
{
|
|
Dsymbol p = sc.parent.pastMixin();
|
|
AggregateDeclaration ad = p.isAggregateDeclaration();
|
|
if (!ad)
|
|
{
|
|
.error(loc, "alias this can only be a member of aggregate, not %s %s", p.kind(), p.toChars());
|
|
return;
|
|
}
|
|
|
|
assert(ad.members);
|
|
Dsymbol s = ad.search(loc, ident);
|
|
if (!s)
|
|
{
|
|
s = sc.search(loc, ident, null);
|
|
if (s)
|
|
.error(loc, "%s is not a member of %s", s.toChars(), ad.toChars());
|
|
else
|
|
.error(loc, "undefined identifier %s", ident.toChars());
|
|
return;
|
|
}
|
|
if (ad.aliasthis && s != ad.aliasthis)
|
|
{
|
|
.error(loc, "there can be only one alias this");
|
|
return;
|
|
}
|
|
|
|
/* disable the alias this conversion so the implicit conversion check
|
|
* doesn't use it.
|
|
*/
|
|
ad.aliasthis = null;
|
|
|
|
Dsymbol sx = s;
|
|
if (sx.isAliasDeclaration())
|
|
sx = sx.toAlias();
|
|
Declaration d = sx.isDeclaration();
|
|
if (d && !d.isTupleDeclaration())
|
|
{
|
|
Type t = d.type;
|
|
assert(t);
|
|
if (ad.type.implicitConvTo(t) > MATCHnomatch)
|
|
{
|
|
.error(loc, "alias this is not reachable as %s already converts to %s", ad.toChars(), t.toChars());
|
|
}
|
|
}
|
|
|
|
ad.aliasthis = s;
|
|
}
|
|
|
|
override const(char)* kind() const
|
|
{
|
|
return "alias this";
|
|
}
|
|
|
|
AliasThis isAliasThis()
|
|
{
|
|
return this;
|
|
}
|
|
|
|
override void accept(Visitor v)
|
|
{
|
|
v.visit(this);
|
|
}
|
|
}
|
|
|
|
extern (C++) Expression resolveAliasThis(Scope* sc, Expression e, bool gag = false)
|
|
{
|
|
AggregateDeclaration ad = isAggregate(e.type);
|
|
if (ad && ad.aliasthis)
|
|
{
|
|
uint olderrors = gag ? global.startGagging() : 0;
|
|
Loc loc = e.loc;
|
|
Type tthis = (e.op == TOKtype ? e.type : null);
|
|
e = new DotIdExp(loc, e, ad.aliasthis.ident);
|
|
e = e.semantic(sc);
|
|
if (tthis && ad.aliasthis.needThis())
|
|
{
|
|
if (e.op == TOKvar)
|
|
{
|
|
if (auto fd = (cast(VarExp)e).var.isFuncDeclaration())
|
|
{
|
|
// Bugzilla 13009: Support better match for the overloaded alias this.
|
|
bool hasOverloads;
|
|
if (auto f = fd.overloadModMatch(loc, tthis, hasOverloads))
|
|
{
|
|
if (!hasOverloads)
|
|
fd = f; // use exact match
|
|
e = new VarExp(loc, fd, hasOverloads);
|
|
e.type = f.type;
|
|
e = new CallExp(loc, e);
|
|
goto L1;
|
|
}
|
|
}
|
|
}
|
|
/* non-@property function is not called inside typeof(),
|
|
* so resolve it ahead.
|
|
*/
|
|
{
|
|
int save = sc.intypeof;
|
|
sc.intypeof = 1; // bypass "need this" error check
|
|
e = resolveProperties(sc, e);
|
|
sc.intypeof = save;
|
|
}
|
|
L1:
|
|
e = new TypeExp(loc, new TypeTypeof(loc, e));
|
|
e = e.semantic(sc);
|
|
}
|
|
e = resolveProperties(sc, e);
|
|
if (gag && global.endGagging(olderrors))
|
|
e = null;
|
|
}
|
|
return e;
|
|
}
|