1
/**
2
 * Implements the `alias this` symbol.
3
 *
4
 * Specification: $(LINK2 https://dlang.org/spec/class.html#alias-this, Alias This)
5
 *
6
 * Copyright:   Copyright (C) 1999-2020 by The D Language Foundation, All Rights Reserved
7
 * Authors:     $(LINK2 http://www.digitalmars.com, Walter Bright)
8
 * License:     $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0)
9
 * Source:      $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/aliasthis.d, _aliasthis.d)
10
 * Documentation:  https://dlang.org/phobos/dmd_aliasthis.html
11
 * Coverage:    https://codecov.io/gh/dlang/dmd/src/master/src/dmd/aliasthis.d
12
 */
13

14
module dmd.aliasthis;
15

16
import core.stdc.stdio;
17
import dmd.aggregate;
18
import dmd.dscope;
19
import dmd.dsymbol;
20
import dmd.expression;
21
import dmd.expressionsem;
22
import dmd.globals;
23
import dmd.identifier;
24
import dmd.mtype;
25
import dmd.opover;
26
import dmd.tokens;
27
import dmd.visitor;
28

29
/***********************************************************
30
 * alias ident this;
31
 */
32
extern (C++) final class AliasThis : Dsymbol
33
{
34
    Identifier ident;
35
    /// The symbol this `alias this` resolves to
36
    Dsymbol sym;
37
    /// Whether this `alias this` is deprecated or not
38
    bool isDeprecated_;
39

40 1
    extern (D) this(const ref Loc loc, Identifier ident)
41
    {
42 1
        super(loc, null);    // it's anonymous (no identifier)
43 1
        this.ident = ident;
44
    }
45

46
    override Dsymbol syntaxCopy(Dsymbol s)
47
    {
48 1
        assert(!s);
49 1
        auto at = new AliasThis(loc, ident);
50 1
        at.comment = comment;
51 1
        return at;
52
    }
53

54
    override const(char)* kind() const
55
    {
56 0
        return "alias this";
57
    }
58

59
    AliasThis isAliasThis()
60
    {
61 0
        return this;
62
    }
63

64
    override void accept(Visitor v)
65
    {
66 1
        v.visit(this);
67
    }
68

69
    override bool isDeprecated() const
70
    {
71 1
        return this.isDeprecated_;
72
    }
73
}
74

75
Expression resolveAliasThis(Scope* sc, Expression e, bool gag = false)
76
{
77 1
    for (AggregateDeclaration ad = isAggregate(e.type); ad;)
78
    {
79 1
        if (ad.aliasthis)
80
        {
81 1
            uint olderrors = gag ? global.startGagging() : 0;
82 1
            Loc loc = e.loc;
83 1
            Type tthis = (e.op == TOK.type ? e.type : null);
84 1
            e = new DotIdExp(loc, e, ad.aliasthis.ident);
85 1
            e = e.expressionSemantic(sc);
86 1
            if (tthis && ad.aliasthis.sym.needThis())
87
            {
88 1
                if (e.op == TOK.variable)
89
                {
90 1
                    if (auto fd = (cast(VarExp)e).var.isFuncDeclaration())
91
                    {
92
                        // https://issues.dlang.org/show_bug.cgi?id=13009
93
                        // Support better match for the overloaded alias this.
94 1
                        bool hasOverloads;
95 1
                        if (auto f = fd.overloadModMatch(loc, tthis, hasOverloads))
96
                        {
97 1
                            if (!hasOverloads)
98 1
                                fd = f;     // use exact match
99 1
                            e = new VarExp(loc, fd, hasOverloads);
100 1
                            e.type = f.type;
101 1
                            e = new CallExp(loc, e);
102 1
                            goto L1;
103
                        }
104
                    }
105
                }
106
                /* non-@property function is not called inside typeof(),
107
                 * so resolve it ahead.
108
                 */
109
                {
110 1
                    int save = sc.intypeof;
111 1
                    sc.intypeof = 1; // bypass "need this" error check
112 1
                    e = resolveProperties(sc, e);
113 1
                    sc.intypeof = save;
114
                }
115
            L1:
116 1
                e = new TypeExp(loc, new TypeTypeof(loc, e));
117 1
                e = e.expressionSemantic(sc);
118
            }
119 1
            e = resolveProperties(sc, e);
120 1
            if (!gag)
121 1
                ad.aliasthis.checkDeprecatedAliasThis(loc, sc);
122 1
            else if (global.endGagging(olderrors))
123 1
                e = null;
124
        }
125

126
        import dmd.dclass : ClassDeclaration;
127 1
        auto cd = ad.isClassDeclaration();
128 1
        if ((!e || !ad.aliasthis) && cd && cd.baseClass && cd.baseClass != ClassDeclaration.object)
129
        {
130 1
            ad = cd.baseClass;
131 1
            continue;
132
        }
133 1
        break;
134
    }
135 1
    return e;
136
}
137

138
/**
139
 * Check if an `alias this` is deprecated
140
 *
141
 * Usually one would use `expression.checkDeprecated(scope, aliasthis)` to
142
 * check if `expression` uses a deprecated `aliasthis`, but this calls
143
 * `toPrettyChars` which lead to the following message:
144
 * "Deprecation: alias this `fullyqualified.aggregate.__anonymous` is deprecated"
145
 *
146
 * Params:
147
 *   at  = The `AliasThis` object to check
148
 *   loc = `Loc` of the expression triggering the access to `at`
149
 *   sc  = `Scope` of the expression
150
 *         (deprecations do not trigger in deprecated scopes)
151
 *
152
 * Returns:
153
 *   Whether the alias this was reported as deprecated.
154
 */
155
bool checkDeprecatedAliasThis(AliasThis at, const ref Loc loc, Scope* sc)
156
{
157
    import dmd.errors : deprecation;
158
    import dmd.dsymbolsem : getMessage;
159

160 1
    if (global.params.useDeprecated != DiagnosticReporting.off
161 1
        && at.isDeprecated() && !sc.isDeprecated())
162
    {
163 1
            const(char)* message = null;
164 1
            for (Dsymbol p = at; p; p = p.parent)
165
            {
166 1
                message = p.depdecl ? p.depdecl.getMessage() : null;
167 1
                if (message)
168 1
                    break;
169
            }
170 1
            if (message)
171 1
                deprecation(loc, "`alias %s this` is deprecated - %s",
172
                            at.sym.toChars(), message);
173
            else
174 1
                deprecation(loc, "`alias %s this` is deprecated",
175
                            at.sym.toChars());
176 1
        return true;
177
    }
178 1
    return false;
179
}

Read our documentation on viewing source code .

Loading