"Fossies" - the Fresh Open Source Software Archive

Member "dmd2/src/dmd/dmd/dscope.d" (20 Nov 2020, 24271 Bytes) of package /linux/misc/dmd.2.094.2.linux.tar.xz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) D source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file.

    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         if (freelist)
  146         {
  147             Scope* s = freelist;
  148             freelist = s.enclosing;
  149             //printf("freelist %p\n", s);
  150             assert(s.flags & SCOPE.free);
  151             s.flags &= ~SCOPE.free;
  152             return s;
  153         }
  154         return new Scope();
  155     }
  156 
  157     extern (D) static Scope* createGlobal(Module _module)
  158     {
  159         Scope* sc = Scope.alloc();
  160         *sc = Scope.init;
  161         sc._module = _module;
  162         sc.minst = _module;
  163         sc.scopesym = new ScopeDsymbol();
  164         sc.scopesym.symtab = new DsymbolTable();
  165         // Add top level package as member of this global scope
  166         Dsymbol m = _module;
  167         while (m.parent)
  168             m = m.parent;
  169         m.addMember(null, sc.scopesym);
  170         m.parent = null; // got changed by addMember()
  171         // Create the module scope underneath the global scope
  172         sc = sc.push(_module);
  173         sc.parent = _module;
  174         return sc;
  175     }
  176 
  177     extern (C++) Scope* copy()
  178     {
  179         Scope* sc = Scope.alloc();
  180         *sc = this;
  181         /* https://issues.dlang.org/show_bug.cgi?id=11777
  182          * The copied scope should not inherit fieldinit.
  183          */
  184         sc.ctorflow.fieldinit = null;
  185         return sc;
  186     }
  187 
  188     extern (C++) Scope* push()
  189     {
  190         Scope* s = copy();
  191         //printf("Scope::push(this = %p) new = %p\n", this, s);
  192         assert(!(flags & SCOPE.free));
  193         s.scopesym = null;
  194         s.enclosing = &this;
  195         debug
  196         {
  197             if (enclosing)
  198                 assert(!(enclosing.flags & SCOPE.free));
  199             if (s == enclosing)
  200             {
  201                 printf("this = %p, enclosing = %p, enclosing.enclosing = %p\n", s, &this, enclosing);
  202             }
  203             assert(s != enclosing);
  204         }
  205         s.slabel = null;
  206         s.nofree = false;
  207         s.ctorflow.fieldinit = ctorflow.fieldinit.arraydup;
  208         s.flags = (flags & SCOPEpush);
  209         s.lastdc = null;
  210         assert(&this != s);
  211         return s;
  212     }
  213 
  214     extern (C++) Scope* push(ScopeDsymbol ss)
  215     {
  216         //printf("Scope::push(%s)\n", ss.toChars());
  217         Scope* s = push();
  218         s.scopesym = ss;
  219         return s;
  220     }
  221 
  222     extern (C++) Scope* pop()
  223     {
  224         //printf("Scope::pop() %p nofree = %d\n", this, nofree);
  225         if (enclosing)
  226             enclosing.ctorflow.OR(ctorflow);
  227         ctorflow.freeFieldinit();
  228 
  229         Scope* enc = enclosing;
  230         if (!nofree)
  231         {
  232             if (mem.isGCEnabled)
  233                 this = this.init;
  234             enclosing = freelist;
  235             freelist = &this;
  236             flags |= SCOPE.free;
  237         }
  238         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         ctorflow.freeFieldinit();
  248         enclosing = null;
  249         pop();
  250     }
  251 
  252     extern (C++) Scope* startCTFE()
  253     {
  254         Scope* sc = this.push();
  255         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         return sc;
  277     }
  278 
  279     extern (C++) Scope* endCTFE()
  280     {
  281         assert(flags & SCOPE.ctfe);
  282         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         if (!mergeCallSuper(this.ctorflow.callSuper, ctorflow.callSuper))
  295             error(loc, "one path skips constructor");
  296 
  297         const fies = ctorflow.fieldinit;
  298         if (this.ctorflow.fieldinit.length && fies.length)
  299         {
  300             FuncDeclaration f = func;
  301             if (fes)
  302                 f = fes.func;
  303             auto ad = f.isMemberDecl();
  304             assert(ad);
  305             foreach (i, v; ad.fields)
  306             {
  307                 bool mustInit = (v.storage_class & STC.nodefaultctor || v.type.needsNested());
  308                 auto fieldInit = &this.ctorflow.fieldinit[i];
  309                 const fiesCurrent = fies[i];
  310                 if (fieldInit.loc is Loc.init)
  311                     fieldInit.loc = fiesCurrent.loc;
  312                 if (!mergeFieldInit(this.ctorflow.fieldinit[i].csx, fiesCurrent.csx) && mustInit)
  313                 {
  314                     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         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         assert(!(flags & (SearchLocalsOnly | SearchImportsOnly)));
  361 
  362         /* If ident is "start at module scope", only look at module scope
  363          */
  364         if (ident == Id.empty)
  365         {
  366             // Look for module scope
  367             for (Scope* sc = &this; sc; sc = sc.enclosing)
  368             {
  369                 assert(sc != sc.enclosing);
  370                 if (!sc.scopesym)
  371                     continue;
  372                 if (Dsymbol s = sc.scopesym.isModule())
  373                 {
  374                     //printMsg("\tfound", s);
  375                     if (pscopesym)
  376                         *pscopesym = sc.scopesym;
  377                     return s;
  378                 }
  379             }
  380             return null;
  381         }
  382 
  383         Dsymbol checkAliasThis(AggregateDeclaration ad, Identifier ident, int flags, Expression* exp)
  384         {
  385             import dmd.mtype;
  386             if (!ad || !ad.aliasthis)
  387                 return null;
  388 
  389             Declaration decl = ad.aliasthis.sym.isDeclaration();
  390             if (!decl)
  391                 return null;
  392 
  393             Type t = decl.type;
  394             ScopeDsymbol sds;
  395             TypeClass tc;
  396             TypeStruct ts;
  397             switch(t.ty)
  398             {
  399                 case Tstruct:
  400                     ts = cast(TypeStruct)t;
  401                     sds = ts.sym;
  402                     break;
  403                 case Tclass:
  404                     tc = cast(TypeClass)t;
  405                     sds = tc.sym;
  406                     break;
  407                 case Tinstance:
  408                     sds = (cast(TypeInstance)t).tempinst;
  409                     break;
  410                 case Tenum:
  411                     sds = (cast(TypeEnum)t).sym;
  412                     break;
  413                 default: break;
  414             }
  415 
  416             if (!sds)
  417                 return null;
  418 
  419             Dsymbol ret = sds.search(loc, ident, flags);
  420             if (ret)
  421             {
  422                 *exp = new DotIdExp(loc, *exp, ad.aliasthis.ident);
  423                 *exp = new DotIdExp(loc, *exp, ident);
  424                 return ret;
  425             }
  426 
  427             if (!ts && !tc)
  428                 return null;
  429 
  430             Dsymbol s;
  431             *exp = new DotIdExp(loc, *exp, ad.aliasthis.ident);
  432             if (ts && !(ts.att & AliasThisRec.tracing))
  433             {
  434                 ts.att = cast(AliasThisRec)(ts.att | AliasThisRec.tracing);
  435                 s = checkAliasThis(sds.isAggregateDeclaration(), ident, flags, exp);
  436                 ts.att = cast(AliasThisRec)(ts.att & ~AliasThisRec.tracing);
  437             }
  438             else if(tc && !(tc.att & AliasThisRec.tracing))
  439             {
  440                 tc.att = cast(AliasThisRec)(tc.att | AliasThisRec.tracing);
  441                 s = checkAliasThis(sds.isAggregateDeclaration(), ident, flags, exp);
  442                 tc.att = cast(AliasThisRec)(tc.att & ~AliasThisRec.tracing);
  443             }
  444             return s;
  445         }
  446 
  447         Dsymbol searchScopes(int flags)
  448         {
  449             for (Scope* sc = &this; sc; sc = sc.enclosing)
  450             {
  451                 assert(sc != sc.enclosing);
  452                 if (!sc.scopesym)
  453                     continue;
  454                 //printf("\tlooking in scopesym '%s', kind = '%s', flags = x%x\n", sc.scopesym.toChars(), sc.scopesym.kind(), flags);
  455 
  456                 if (sc.scopesym.isModule())
  457                     flags |= SearchUnqualifiedModule;        // tell Module.search() that SearchLocalsOnly is to be obeyed
  458 
  459                 if (Dsymbol s = sc.scopesym.search(loc, ident, flags))
  460                 {
  461                     if (!(flags & (SearchImportsOnly | IgnoreErrors)) &&
  462                         ident == Id.length && sc.scopesym.isArrayScopeSymbol() &&
  463                         sc.enclosing && sc.enclosing.search(loc, ident, null, flags))
  464                     {
  465                         warning(s.loc, "array `length` hides other `length` name in outer scope");
  466                     }
  467                     //printMsg("\tfound local", s);
  468                     if (pscopesym)
  469                         *pscopesym = sc.scopesym;
  470                     return s;
  471                 }
  472 
  473                 if (global.params.fixAliasThis)
  474                 {
  475                     Expression exp = new ThisExp(loc);
  476                     Dsymbol aliasSym = checkAliasThis(sc.scopesym.isAggregateDeclaration(), ident, flags, &exp);
  477                     if (aliasSym)
  478                     {
  479                         //printf("found aliassym: %s\n", aliasSym.toChars());
  480                         if (pscopesym)
  481                             *pscopesym = new ExpressionDsymbol(exp);
  482                         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                 if (sc.scopesym.isModule() && !(sc.enclosing && !sc.enclosing.enclosing))
  488                     break;
  489             }
  490             return null;
  491         }
  492 
  493         if (this.flags & SCOPE.ignoresymbolvisibility)
  494             flags |= IgnoreSymbolVisibility;
  495 
  496         // First look in local scopes
  497         Dsymbol s = searchScopes(flags | SearchLocalsOnly);
  498         version (LOGSEARCH) if (s) printMsg("-Scope.search() found local", s);
  499         if (!s)
  500         {
  501             // Second look in imported modules
  502             s = searchScopes(flags | SearchImportsOnly);
  503             version (LOGSEARCH) if (s) printMsg("-Scope.search() found import", s);
  504         }
  505         return s;
  506     }
  507 
  508     extern (D) Dsymbol search_correct(Identifier ident)
  509     {
  510         if (global.gag)
  511             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             if (!seed.length)
  524                 return null;
  525             Identifier id = Identifier.lookup(seed);
  526             if (!id)
  527                 return null;
  528             Scope* sc = &this;
  529             Module.clearCache();
  530             Dsymbol scopesym = null;
  531             Dsymbol s = sc.search(Loc.initial, id, &scopesym, IgnoreErrors);
  532             if (!s)
  533                 return null;
  534 
  535             // Do not show `@disable`d declarations
  536             if (auto decl = s.isDeclaration())
  537                 if (decl.storage_class & STC.disable)
  538                     return null;
  539             // Or `deprecated` ones if we're not in a deprecated scope
  540             if (s.isDeprecated() && !sc.isDeprecated())
  541                 return null;
  542 
  543             for (cost = 0; sc; sc = sc.enclosing, ++cost)
  544                 if (sc.scopesym == scopesym)
  545                     break;
  546             if (scopesym != s.parent)
  547             {
  548                 ++cost; // got to the symbol through an import
  549                 if (s.prot().kind == Prot.Kind.private_)
  550                     return null;
  551             }
  552             return s;
  553         }
  554 
  555         Dsymbol scopesym = null;
  556         // search for exact name first
  557         if (auto s = search(Loc.initial, ident, &scopesym, IgnoreErrors))
  558             return s;
  559         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         TOK tok;
  573         if (ident == Id.NULL)
  574             tok = TOK.null_;
  575         else if (ident == Id.TRUE)
  576             tok = TOK.true_;
  577         else if (ident == Id.FALSE)
  578             tok = TOK.false_;
  579         else if (ident == Id.unsigned)
  580             tok = TOK.uns32;
  581         else if (ident == Id.wchar_t)
  582             tok = global.params.isWindows ? TOK.wchar_ : TOK.dchar_;
  583         else
  584             return null;
  585         return Token.toChars(tok);
  586     }
  587 
  588     extern (D) Dsymbol insert(Dsymbol s)
  589     {
  590         if (VarDeclaration vd = s.isVarDeclaration())
  591         {
  592             if (lastVar)
  593                 vd.lastVar = lastVar;
  594             lastVar = vd;
  595         }
  596         else if (WithScopeSymbol ss = s.isWithScopeSymbol())
  597         {
  598             if (VarDeclaration vd = ss.withstate.wthis)
  599             {
  600                 if (lastVar)
  601                     vd.lastVar = lastVar;
  602                 lastVar = vd;
  603             }
  604             return null;
  605         }
  606         for (Scope* sc = &this; sc; sc = sc.enclosing)
  607         {
  608             //printf("\tsc = %p\n", sc);
  609             if (sc.scopesym)
  610             {
  611                 //printf("\t\tsc.scopesym = %p\n", sc.scopesym);
  612                 if (!sc.scopesym.symtab)
  613                     sc.scopesym.symtab = new DsymbolTable();
  614                 return sc.scopesym.symtabInsert(s);
  615             }
  616         }
  617         assert(0);
  618     }
  619 
  620     /********************************************
  621      * Search enclosing scopes for ClassDeclaration.
  622      */
  623     extern (C++) ClassDeclaration getClassScope()
  624     {
  625         for (Scope* sc = &this; sc; sc = sc.enclosing)
  626         {
  627             if (!sc.scopesym)
  628                 continue;
  629             ClassDeclaration cd = sc.scopesym.isClassDeclaration();
  630             if (cd)
  631                 return cd;
  632         }
  633         return null;
  634     }
  635 
  636     /********************************************
  637      * Search enclosing scopes for ClassDeclaration.
  638      */
  639     extern (C++) AggregateDeclaration getStructClassScope()
  640     {
  641         for (Scope* sc = &this; sc; sc = sc.enclosing)
  642         {
  643             if (!sc.scopesym)
  644                 continue;
  645             AggregateDeclaration ad = sc.scopesym.isClassDeclaration();
  646             if (ad)
  647                 return ad;
  648             ad = sc.scopesym.isStructDeclaration();
  649             if (ad)
  650                 return ad;
  651         }
  652         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         for (Scope* sc = &this; sc; sc = sc.enclosing)
  665         {
  666             //printf("\tsc = %p\n", sc);
  667             sc.nofree = true;
  668             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         if (aligndecl)
  679             return aligndecl.getAlignment(&this);
  680         else
  681             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         for (const(Dsymbol)* sp = &(this.parent); *sp; sp = &(sp.parent))
  692         {
  693             if (sp.isDeprecated())
  694                 return true;
  695         }
  696         for (const(Scope)* sc2 = &this; sc2; sc2 = sc2.enclosing)
  697         {
  698             if (sc2.scopesym && sc2.scopesym.isDeprecated())
  699                 return true;
  700 
  701             // If inside a StorageClassDeclaration that is deprecated
  702             if (sc2.stc & STC.deprecated_)
  703                 return true;
  704         }
  705         if (_module.md && _module.md.isdeprecated)
  706         {
  707             return true;
  708         }
  709         return false;
  710     }
  711 }