1
/**
2
 * A scope as defined by curly braces `{}`.
3
 *
4
 * Not to be confused with the `scope` storage class.
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/dscope.d, _dscope.d)
10
 * Documentation:  https://dlang.org/phobos/dmd_dscope.html
11
 * Coverage:    https://codecov.io/gh/dlang/dmd/src/master/src/dmd/dscope.d
12
 */
13

14
module dmd.dscope;
15

16
import core.stdc.stdio;
17
import core.stdc.string;
18
import dmd.aggregate;
19
import dmd.arraytypes;
20
import dmd.attrib;
21
import dmd.ctorflow;
22
import dmd.dclass;
23
import dmd.declaration;
24
import dmd.dmodule;
25
import dmd.doc;
26
import dmd.dsymbol;
27
import dmd.dsymbolsem;
28
import dmd.dtemplate;
29
import dmd.expression;
30
import dmd.errors;
31
import dmd.func;
32
import dmd.globals;
33
import dmd.id;
34
import dmd.identifier;
35
import dmd.root.outbuffer;
36
import dmd.root.rmem;
37
import dmd.root.speller;
38
import dmd.statement;
39
import dmd.tokens;
40

41
//version=LOGSEARCH;
42

43

44
// Flags that would not be inherited beyond scope nesting
45
enum SCOPE
46
{
47
    ctor          = 0x0001,   /// constructor type
48
    noaccesscheck = 0x0002,   /// don't do access checks
49
    condition     = 0x0004,   /// inside static if/assert condition
50
    debug_        = 0x0008,   /// inside debug conditional
51
    constraint    = 0x0010,   /// inside template constraint
52
    invariant_    = 0x0020,   /// inside invariant code
53
    require       = 0x0040,   /// inside in contract code
54
    ensure        = 0x0060,   /// inside out contract code
55
    contract      = 0x0060,   /// [mask] we're inside contract code
56
    ctfe          = 0x0080,   /// inside a ctfe-only expression
57
    compile       = 0x0100,   /// inside __traits(compile)
58
    ignoresymbolvisibility    = 0x0200,   /// ignore symbol visibility
59
                                          /// https://issues.dlang.org/show_bug.cgi?id=15907
60
    onlysafeaccess = 0x0400,  /// unsafe access is not allowed for @safe code
61
    free          = 0x8000,   /// is on free list
62

63
    fullinst      = 0x10000,  /// fully instantiate templates
64
    alias_        = 0x20000,  /// inside alias declaration.
65

66
    // The following are mutually exclusive
67
    printf        = 0x4_0000, /// printf-style function
68
    scanf         = 0x8_0000, /// scanf-style function
69
}
70

71
// Flags that are carried along with a scope push()
72
enum SCOPEpush = SCOPE.contract | SCOPE.debug_ | SCOPE.ctfe | SCOPE.compile | SCOPE.constraint |
73
                 SCOPE.noaccesscheck | SCOPE.onlysafeaccess | SCOPE.ignoresymbolvisibility |
74
                 SCOPE.printf | SCOPE.scanf;
75

76
struct Scope
77
{
78
    Scope* enclosing;               /// enclosing Scope
79

80
    Module _module;                 /// Root module
81
    ScopeDsymbol scopesym;          /// current symbol
82
    FuncDeclaration func;           /// function we are in
83
    Dsymbol parent;                 /// parent to use
84
    LabelStatement slabel;          /// enclosing labelled statement
85
    SwitchStatement sw;             /// enclosing switch statement
86
    Statement tryBody;              /// enclosing _body of TryCatchStatement or TryFinallyStatement
87
    TryFinallyStatement tf;         /// enclosing try finally statement
88
    ScopeGuardStatement os;            /// enclosing scope(xxx) statement
89
    Statement sbreak;               /// enclosing statement that supports "break"
90
    Statement scontinue;            /// enclosing statement that supports "continue"
91
    ForeachStatement fes;           /// if nested function for ForeachStatement, this is it
92
    Scope* callsc;                  /// used for __FUNCTION__, __PRETTY_FUNCTION__ and __MODULE__
93
    Dsymbol inunion;                /// != null if processing members of a union
94
    bool nofree;                    /// true if shouldn't free it
95
    bool inLoop;                    /// true if inside a loop (where constructor calls aren't allowed)
96
    int intypeof;                   /// in typeof(exp)
97
    VarDeclaration lastVar;         /// Previous symbol used to prevent goto-skips-init
98

99
    /* If  minst && !tinst, it's in definitely non-speculative scope (eg. module member scope).
100
     * If !minst && !tinst, it's in definitely speculative scope (eg. template constraint).
101
     * If  minst &&  tinst, it's in instantiated code scope without speculation.
102
     * If !minst &&  tinst, it's in instantiated code scope with speculation.
103
     */
104
    Module minst;                   /// root module where the instantiated templates should belong to
105
    TemplateInstance tinst;         /// enclosing template instance
106

107
    CtorFlow ctorflow;              /// flow analysis for constructors
108

109
    /// alignment for struct members
110
    AlignDeclaration aligndecl;
111

112
    /// C++ namespace this symbol is in
113
    CPPNamespaceDeclaration namespace;
114

115
    /// linkage for external functions
116
    LINK linkage = LINK.d;
117

118
    /// mangle type
119
    CPPMANGLE cppmangle = CPPMANGLE.def;
120

121
    /// inlining strategy for functions
122
    PINLINE inlining = PINLINE.default_;
123

124
    /// protection for class members
125
    Prot protection = Prot(Prot.Kind.public_);
126
    int explicitProtection;         /// set if in an explicit protection attribute
127

128
    StorageClass stc;               /// storage class
129

130
    DeprecatedDeclaration depdecl;  /// customized deprecation message
131

132
    uint flags;
133

134
    // user defined attributes
135
    UserAttributeDeclaration userAttribDecl;
136

137
    DocComment* lastdc;        /// documentation comment for last symbol at this scope
138
    uint[void*] anchorCounts;  /// lookup duplicate anchor name count
139
    Identifier prevAnchor;     /// qualified symbol name of last doc anchor
140

141
    extern (D) __gshared Scope* freelist;
142

143
    extern (D) static Scope* alloc()
144
    {
145 1
        if (freelist)
146
        {
147 1
            Scope* s = freelist;
148 1
            freelist = s.enclosing;
149
            //printf("freelist %p\n", s);
150 1
            assert(s.flags & SCOPE.free);
151 1
            s.flags &= ~SCOPE.free;
152 1
            return s;
153
        }
154 1
        return new Scope();
155
    }
156

157
    extern (D) static Scope* createGlobal(Module _module)
158
    {
159 1
        Scope* sc = Scope.alloc();
160 1
        *sc = Scope.init;
161 1
        sc._module = _module;
162 1
        sc.minst = _module;
163 1
        sc.scopesym = new ScopeDsymbol();
164 1
        sc.scopesym.symtab = new DsymbolTable();
165
        // Add top level package as member of this global scope
166 1
        Dsymbol m = _module;
167 1
        while (m.parent)
168 1
            m = m.parent;
169 1
        m.addMember(null, sc.scopesym);
170 1
        m.parent = null; // got changed by addMember()
171
        // Create the module scope underneath the global scope
172 1
        sc = sc.push(_module);
173 1
        sc.parent = _module;
174 1
        return sc;
175
    }
176

177
    extern (C++) Scope* copy()
178
    {
179 1
        Scope* sc = Scope.alloc();
180 1
        *sc = this;
181
        /* https://issues.dlang.org/show_bug.cgi?id=11777
182
         * The copied scope should not inherit fieldinit.
183
         */
184 1
        sc.ctorflow.fieldinit = null;
185 1
        return sc;
186
    }
187

188
    extern (C++) Scope* push()
189
    {
190 1
        Scope* s = copy();
191
        //printf("Scope::push(this = %p) new = %p\n", this, s);
192 1
        assert(!(flags & SCOPE.free));
193 1
        s.scopesym = null;
194 1
        s.enclosing = &this;
195
        debug
196
        {
197 1
            if (enclosing)
198 1
                assert(!(enclosing.flags & SCOPE.free));
199 1
            if (s == enclosing)
200
            {
201 0
                printf("this = %p, enclosing = %p, enclosing.enclosing = %p\n", s, &this, enclosing);
202
            }
203 1
            assert(s != enclosing);
204
        }
205 1
        s.slabel = null;
206 1
        s.nofree = false;
207 1
        s.ctorflow.fieldinit = ctorflow.fieldinit.arraydup;
208 1
        s.flags = (flags & SCOPEpush);
209 1
        s.lastdc = null;
210 1
        assert(&this != s);
211 1
        return s;
212
    }
213

214
    extern (C++) Scope* push(ScopeDsymbol ss)
215
    {
216
        //printf("Scope::push(%s)\n", ss.toChars());
217 1
        Scope* s = push();
218 1
        s.scopesym = ss;
219 1
        return s;
220
    }
221

222
    extern (C++) Scope* pop()
223
    {
224
        //printf("Scope::pop() %p nofree = %d\n", this, nofree);
225 1
        if (enclosing)
226 1
            enclosing.ctorflow.OR(ctorflow);
227 1
        ctorflow.freeFieldinit();
228

229 1
        Scope* enc = enclosing;
230 1
        if (!nofree)
231
        {
232 1
            if (mem.isGCEnabled)
233 1
                this = this.init;
234 1
            enclosing = freelist;
235 1
            freelist = &this;
236 1
            flags |= SCOPE.free;
237
        }
238 1
        return enc;
239
    }
240

241
    /*************************
242
     * Similar to pop(), but the results in `this` are not folded
243
     * into `enclosing`.
244
     */
245
    extern (D) void detach()
246
    {
247 1
        ctorflow.freeFieldinit();
248 1
        enclosing = null;
249 1
        pop();
250
    }
251

252
    extern (C++) Scope* startCTFE()
253
    {
254 1
        Scope* sc = this.push();
255 1
        sc.flags = this.flags | SCOPE.ctfe;
256
        version (none)
257
        {
258
            /* TODO: Currently this is not possible, because we need to
259
             * unspeculative some types and symbols if they are necessary for the
260
             * final executable. Consider:
261
             *
262
             * struct S(T) {
263
             *   string toString() const { return "instantiated"; }
264
             * }
265
             * enum x = S!int();
266
             * void main() {
267
             *   // To call x.toString in runtime, compiler should unspeculative S!int.
268
             *   assert(x.toString() == "instantiated");
269
             * }
270
             */
271
            // If a template is instantiated from CT evaluated expression,
272
            // compiler can elide its code generation.
273
            sc.tinst = null;
274
            sc.minst = null;
275
        }
276 1
        return sc;
277
    }
278

279
    extern (C++) Scope* endCTFE()
280
    {
281 1
        assert(flags & SCOPE.ctfe);
282 1
        return pop();
283
    }
284

285

286
    /*******************************
287
     * Merge results of `ctorflow` into `this`.
288
     * Params:
289
     *   loc = for error messages
290
     *   ctorflow = flow results to merge in
291
     */
292
    extern (D) void merge(const ref Loc loc, const ref CtorFlow ctorflow)
293
    {
294 1
        if (!mergeCallSuper(this.ctorflow.callSuper, ctorflow.callSuper))
295 1
            error(loc, "one path skips constructor");
296

297 1
        const fies = ctorflow.fieldinit;
298 1
        if (this.ctorflow.fieldinit.length && fies.length)
299
        {
300 1
            FuncDeclaration f = func;
301 1
            if (fes)
302 0
                f = fes.func;
303 1
            auto ad = f.isMemberDecl();
304 1
            assert(ad);
305 1
            foreach (i, v; ad.fields)
306
            {
307 1
                bool mustInit = (v.storage_class & STC.nodefaultctor || v.type.needsNested());
308 1
                auto fieldInit = &this.ctorflow.fieldinit[i];
309 1
                const fiesCurrent = fies[i];
310 1
                if (fieldInit.loc is Loc.init)
311 1
                    fieldInit.loc = fiesCurrent.loc;
312 1
                if (!mergeFieldInit(this.ctorflow.fieldinit[i].csx, fiesCurrent.csx) && mustInit)
313
                {
314 1
                    error(loc, "one path skips field `%s`", v.toChars());
315
                }
316
            }
317
        }
318
    }
319

320
    extern (C++) Module instantiatingModule()
321
    {
322
        // TODO: in speculative context, returning 'module' is correct?
323 1
        return minst ? minst : _module;
324
    }
325

326
    /************************************
327
     * Perform unqualified name lookup by following the chain of scopes up
328
     * until found.
329
     *
330
     * Params:
331
     *  loc = location to use for error messages
332
     *  ident = name to look up
333
     *  pscopesym = if supplied and name is found, set to scope that ident was found in
334
     *  flags = modify search based on flags
335
     *
336
     * Returns:
337
     *  symbol if found, null if not
338
     */
339
    extern (C++) Dsymbol search(const ref Loc loc, Identifier ident, Dsymbol* pscopesym, int flags = IgnoreNone)
340
    {
341
        version (LOGSEARCH)
342
        {
343
            printf("Scope.search(%p, '%s' flags=x%x)\n", &this, ident.toChars(), flags);
344
            // Print scope chain
345
            for (Scope* sc = &this; sc; sc = sc.enclosing)
346
            {
347
                if (!sc.scopesym)
348
                    continue;
349
                printf("\tscope %s\n", sc.scopesym.toChars());
350
            }
351

352
            static void printMsg(string txt, Dsymbol s)
353
            {
354
                printf("%.*s  %s.%s, kind = '%s'\n", cast(int)txt.length, txt.ptr,
355
                    s.parent ? s.parent.toChars() : "", s.toChars(), s.kind());
356
            }
357
        }
358

359
        // This function is called only for unqualified lookup
360 1
        assert(!(flags & (SearchLocalsOnly | SearchImportsOnly)));
361

362
        /* If ident is "start at module scope", only look at module scope
363
         */
364 1
        if (ident == Id.empty)
365
        {
366
            // Look for module scope
367 1
            for (Scope* sc = &this; sc; sc = sc.enclosing)
368
            {
369 1
                assert(sc != sc.enclosing);
370 1
                if (!sc.scopesym)
371 1
                    continue;
372 1
                if (Dsymbol s = sc.scopesym.isModule())
373
                {
374
                    //printMsg("\tfound", s);
375 1
                    if (pscopesym)
376 1
                        *pscopesym = sc.scopesym;
377 1
                    return s;
378
                }
379
            }
380 0
            return null;
381
        }
382

383
        Dsymbol checkAliasThis(AggregateDeclaration ad, Identifier ident, int flags, Expression* exp)
384
        {
385
            import dmd.mtype;
386 1
            if (!ad || !ad.aliasthis)
387 1
                return null;
388

389 1
            Declaration decl = ad.aliasthis.sym.isDeclaration();
390 1
            if (!decl)
391 0
                return null;
392

393 1
            Type t = decl.type;
394 1
            ScopeDsymbol sds;
395 1
            TypeClass tc;
396 1
            TypeStruct ts;
397 1
            switch(t.ty)
398
            {
399 1
                case Tstruct:
400 1
                    ts = cast(TypeStruct)t;
401 1
                    sds = ts.sym;
402 1
                    break;
403 0
                case Tclass:
404 0
                    tc = cast(TypeClass)t;
405 0
                    sds = tc.sym;
406 0
                    break;
407 0
                case Tinstance:
408 0
                    sds = (cast(TypeInstance)t).tempinst;
409 0
                    break;
410 0
                case Tenum:
411 0
                    sds = (cast(TypeEnum)t).sym;
412 0
                    break;
413 0
                default: break;
414
            }
415

416 1
            if (!sds)
417 0
                return null;
418

419 1
            Dsymbol ret = sds.search(loc, ident, flags);
420 1
            if (ret)
421
            {
422 1
                *exp = new DotIdExp(loc, *exp, ad.aliasthis.ident);
423 1
                *exp = new DotIdExp(loc, *exp, ident);
424 1
                return ret;
425
            }
426

427 1
            if (!ts && !tc)
428 0
                return null;
429

430 1
            Dsymbol s;
431 1
            *exp = new DotIdExp(loc, *exp, ad.aliasthis.ident);
432 1
            if (ts && !(ts.att & AliasThisRec.tracing))
433
            {
434 1
                ts.att = cast(AliasThisRec)(ts.att | AliasThisRec.tracing);
435 1
                s = checkAliasThis(sds.isAggregateDeclaration(), ident, flags, exp);
436 1
                ts.att = cast(AliasThisRec)(ts.att & ~AliasThisRec.tracing);
437
            }
438 0
            else if(tc && !(tc.att & AliasThisRec.tracing))
439
            {
440 0
                tc.att = cast(AliasThisRec)(tc.att | AliasThisRec.tracing);
441 0
                s = checkAliasThis(sds.isAggregateDeclaration(), ident, flags, exp);
442 0
                tc.att = cast(AliasThisRec)(tc.att & ~AliasThisRec.tracing);
443
            }
444 1
            return s;
445
        }
446

447
        Dsymbol searchScopes(int flags)
448
        {
449 1
            for (Scope* sc = &this; sc; sc = sc.enclosing)
450
            {
451 1
                assert(sc != sc.enclosing);
452 1
                if (!sc.scopesym)
453 1
                    continue;
454
                //printf("\tlooking in scopesym '%s', kind = '%s', flags = x%x\n", sc.scopesym.toChars(), sc.scopesym.kind(), flags);
455

456 1
                if (sc.scopesym.isModule())
457 1
                    flags |= SearchUnqualifiedModule;        // tell Module.search() that SearchLocalsOnly is to be obeyed
458

459 1
                if (Dsymbol s = sc.scopesym.search(loc, ident, flags))
460
                {
461 1
                    if (!(flags & (SearchImportsOnly | IgnoreErrors)) &&
462 1
                        ident == Id.length && sc.scopesym.isArrayScopeSymbol() &&
463 0
                        sc.enclosing && sc.enclosing.search(loc, ident, null, flags))
464
                    {
465 0
                        warning(s.loc, "array `length` hides other `length` name in outer scope");
466
                    }
467
                    //printMsg("\tfound local", s);
468 1
                    if (pscopesym)
469 1
                        *pscopesym = sc.scopesym;
470 1
                    return s;
471
                }
472

473 1
                if (global.params.fixAliasThis)
474
                {
475 1
                    Expression exp = new ThisExp(loc);
476 1
                    Dsymbol aliasSym = checkAliasThis(sc.scopesym.isAggregateDeclaration(), ident, flags, &exp);
477 1
                    if (aliasSym)
478
                    {
479
                        //printf("found aliassym: %s\n", aliasSym.toChars());
480 1
                        if (pscopesym)
481 1
                            *pscopesym = new ExpressionDsymbol(exp);
482 1
                        return aliasSym;
483
                    }
484
                }
485

486
                // Stop when we hit a module, but keep going if that is not just under the global scope
487 1
                if (sc.scopesym.isModule() && !(sc.enclosing && !sc.enclosing.enclosing))
488 1
                    break;
489
            }
490 1
            return null;
491
        }
492

493 1
        if (this.flags & SCOPE.ignoresymbolvisibility)
494 1
            flags |= IgnoreSymbolVisibility;
495

496
        // First look in local scopes
497 1
        Dsymbol s = searchScopes(flags | SearchLocalsOnly);
498
        version (LOGSEARCH) if (s) printMsg("-Scope.search() found local", s);
499 1
        if (!s)
500
        {
501
            // Second look in imported modules
502 1
            s = searchScopes(flags | SearchImportsOnly);
503
            version (LOGSEARCH) if (s) printMsg("-Scope.search() found import", s);
504
        }
505 1
        return s;
506
    }
507

508
    extern (D) Dsymbol search_correct(Identifier ident)
509
    {
510 1
        if (global.gag)
511 1
            return null; // don't do it for speculative compiles; too time consuming
512

513
        /************************************************
514
         * Given the failed search attempt, try to find
515
         * one with a close spelling.
516
         */
517
        extern (D) Dsymbol scope_search_fp(const(char)[] seed, ref int cost)
518
        {
519
            //printf("scope_search_fp('%s')\n", seed);
520
            /* If not in the lexer's string table, it certainly isn't in the symbol table.
521
             * Doing this first is a lot faster.
522
             */
523 1
            if (!seed.length)
524 0
                return null;
525 1
            Identifier id = Identifier.lookup(seed);
526 1
            if (!id)
527 1
                return null;
528 1
            Scope* sc = &this;
529 1
            Module.clearCache();
530 1
            Dsymbol scopesym = null;
531 1
            Dsymbol s = sc.search(Loc.initial, id, &scopesym, IgnoreErrors);
532 1
            if (!s)
533 1
                return null;
534

535
            // Do not show `@disable`d declarations
536 1
            if (auto decl = s.isDeclaration())
537 1
                if (decl.storage_class & STC.disable)
538 1
                    return null;
539
            // Or `deprecated` ones if we're not in a deprecated scope
540 1
            if (s.isDeprecated() && !sc.isDeprecated())
541 1
                return null;
542

543 1
            for (cost = 0; sc; sc = sc.enclosing, ++cost)
544 1
                if (sc.scopesym == scopesym)
545 1
                    break;
546 1
            if (scopesym != s.parent)
547
            {
548 1
                ++cost; // got to the symbol through an import
549 1
                if (s.prot().kind == Prot.Kind.private_)
550 0
                    return null;
551
            }
552 1
            return s;
553
        }
554

555 1
        Dsymbol scopesym = null;
556
        // search for exact name first
557 1
        if (auto s = search(Loc.initial, ident, &scopesym, IgnoreErrors))
558 0
            return s;
559 1
        return speller!scope_search_fp(ident.toString());
560
    }
561

562
    /************************************
563
     * Maybe `ident` was a C or C++ name. Check for that,
564
     * and suggest the D equivalent.
565
     * Params:
566
     *  ident = unknown identifier
567
     * Returns:
568
     *  D identifier string if found, null if not
569
     */
570
    extern (D) static const(char)* search_correct_C(Identifier ident)
571
    {
572 1
        TOK tok;
573 1
        if (ident == Id.NULL)
574 1
            tok = TOK.null_;
575 1
        else if (ident == Id.TRUE)
576 1
            tok = TOK.true_;
577 1
        else if (ident == Id.FALSE)
578 1
            tok = TOK.false_;
579 1
        else if (ident == Id.unsigned)
580 1
            tok = TOK.uns32;
581 1
        else if (ident == Id.wchar_t)
582 1
            tok = global.params.isWindows ? TOK.wchar_ : TOK.dchar_;
583
        else
584 1
            return null;
585 1
        return Token.toChars(tok);
586
    }
587

588
    extern (D) Dsymbol insert(Dsymbol s)
589
    {
590 1
        if (VarDeclaration vd = s.isVarDeclaration())
591
        {
592 1
            if (lastVar)
593 1
                vd.lastVar = lastVar;
594 1
            lastVar = vd;
595
        }
596 1
        else if (WithScopeSymbol ss = s.isWithScopeSymbol())
597
        {
598 1
            if (VarDeclaration vd = ss.withstate.wthis)
599
            {
600 1
                if (lastVar)
601 1
                    vd.lastVar = lastVar;
602 1
                lastVar = vd;
603
            }
604 1
            return null;
605
        }
606 1
        for (Scope* sc = &this; sc; sc = sc.enclosing)
607
        {
608
            //printf("\tsc = %p\n", sc);
609 1
            if (sc.scopesym)
610
            {
611
                //printf("\t\tsc.scopesym = %p\n", sc.scopesym);
612 1
                if (!sc.scopesym.symtab)
613 1
                    sc.scopesym.symtab = new DsymbolTable();
614 1
                return sc.scopesym.symtabInsert(s);
615
            }
616
        }
617 0
        assert(0);
618
    }
619

620
    /********************************************
621
     * Search enclosing scopes for ClassDeclaration.
622
     */
623
    extern (C++) ClassDeclaration getClassScope()
624
    {
625 0
        for (Scope* sc = &this; sc; sc = sc.enclosing)
626
        {
627 0
            if (!sc.scopesym)
628 0
                continue;
629 0
            ClassDeclaration cd = sc.scopesym.isClassDeclaration();
630 0
            if (cd)
631 0
                return cd;
632
        }
633 0
        return null;
634
    }
635

636
    /********************************************
637
     * Search enclosing scopes for ClassDeclaration.
638
     */
639
    extern (C++) AggregateDeclaration getStructClassScope()
640
    {
641 1
        for (Scope* sc = &this; sc; sc = sc.enclosing)
642
        {
643 1
            if (!sc.scopesym)
644 1
                continue;
645 1
            AggregateDeclaration ad = sc.scopesym.isClassDeclaration();
646 1
            if (ad)
647 1
                return ad;
648 1
            ad = sc.scopesym.isStructDeclaration();
649 1
            if (ad)
650 1
                return ad;
651
        }
652 1
        return null;
653
    }
654

655
    /*******************************************
656
     * For TemplateDeclarations, we need to remember the Scope
657
     * where it was declared. So mark the Scope as not
658
     * to be free'd.
659
     */
660
    extern (D) void setNoFree()
661
    {
662
        //int i = 0;
663
        //printf("Scope::setNoFree(this = %p)\n", this);
664 1
        for (Scope* sc = &this; sc; sc = sc.enclosing)
665
        {
666
            //printf("\tsc = %p\n", sc);
667 1
            sc.nofree = true;
668 1
            assert(!(flags & SCOPE.free));
669
            //assert(sc != sc.enclosing);
670
            //assert(!sc.enclosing || sc != sc.enclosing.enclosing);
671
            //if (++i == 10)
672
            //    assert(0);
673
        }
674
    }
675

676
    structalign_t alignment()
677
    {
678 1
        if (aligndecl)
679 1
            return aligndecl.getAlignment(&this);
680
        else
681 1
            return STRUCTALIGN_DEFAULT;
682
    }
683

684
    /**********************************
685
    * Checks whether the current scope (or any of its parents) is deprecated.
686
    *
687
    * Returns: `true` if this or any parent scope is deprecated, `false` otherwise`
688
    */
689
    extern(C++) bool isDeprecated() const
690
    {
691 1
        for (const(Dsymbol)* sp = &(this.parent); *sp; sp = &(sp.parent))
692
        {
693 1
            if (sp.isDeprecated())
694 1
                return true;
695
        }
696 1
        for (const(Scope)* sc2 = &this; sc2; sc2 = sc2.enclosing)
697
        {
698 1
            if (sc2.scopesym && sc2.scopesym.isDeprecated())
699 0
                return true;
700

701
            // If inside a StorageClassDeclaration that is deprecated
702 1
            if (sc2.stc & STC.deprecated_)
703 1
                return true;
704
        }
705 1
        if (_module.md && _module.md.isdeprecated)
706
        {
707 1
            return true;
708
        }
709 1
        return false;
710
    }
711
}

Read our documentation on viewing source code .

Loading