"Fossies" - the Fresh Open Source Software Archive

Member "dmd2/src/dmd/dmd/declaration.d" (20 Nov 2020, 67977 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  * Miscellaneous declarations, including typedef, alias, variable declarations including the
    3  * implicit this declaration, type tuples, ClassInfo, ModuleInfo and various TypeInfos.
    4  *
    5  * Copyright:   Copyright (C) 1999-2020 by The D Language Foundation, All Rights Reserved
    6  * Authors:     $(LINK2 http://www.digitalmars.com, Walter Bright)
    7  * License:     $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0)
    8  * Source:      $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/declaration.d, _declaration.d)
    9  * Documentation:  https://dlang.org/phobos/dmd_declaration.html
   10  * Coverage:    https://codecov.io/gh/dlang/dmd/src/master/src/dmd/declaration.d
   11  */
   12 
   13 module dmd.declaration;
   14 
   15 import core.stdc.stdio;
   16 import dmd.aggregate;
   17 import dmd.arraytypes;
   18 import dmd.ctorflow;
   19 import dmd.dclass;
   20 import dmd.delegatize;
   21 import dmd.dscope;
   22 import dmd.dstruct;
   23 import dmd.dsymbol;
   24 import dmd.dsymbolsem;
   25 import dmd.dtemplate;
   26 import dmd.errors;
   27 import dmd.expression;
   28 import dmd.func;
   29 import dmd.globals;
   30 import dmd.id;
   31 import dmd.identifier;
   32 import dmd.init;
   33 import dmd.initsem;
   34 import dmd.intrange;
   35 import dmd.mtype;
   36 import dmd.root.outbuffer;
   37 import dmd.root.rootobject;
   38 import dmd.target;
   39 import dmd.tokens;
   40 import dmd.typesem;
   41 import dmd.visitor;
   42 
   43 /************************************
   44  * Check to see the aggregate type is nested and its context pointer is
   45  * accessible from the current scope.
   46  * Returns true if error occurs.
   47  */
   48 bool checkFrameAccess(Loc loc, Scope* sc, AggregateDeclaration ad, size_t iStart = 0)
   49 {
   50     Dsymbol sparent = ad.toParentLocal();
   51     Dsymbol sparent2 = ad.toParent2();
   52     Dsymbol s = sc.func;
   53     if (ad.isNested() && s)
   54     {
   55         //printf("ad = %p %s [%s], parent:%p\n", ad, ad.toChars(), ad.loc.toChars(), ad.parent);
   56         //printf("sparent = %p %s [%s], parent: %s\n", sparent, sparent.toChars(), sparent.loc.toChars(), sparent.parent,toChars());
   57         //printf("sparent2 = %p %s [%s], parent: %s\n", sparent2, sparent2.toChars(), sparent2.loc.toChars(), sparent2.parent,toChars());
   58         if (!ensureStaticLinkTo(s, sparent) || sparent != sparent2 && !ensureStaticLinkTo(s, sparent2))
   59         {
   60             error(loc, "cannot access frame pointer of `%s`", ad.toPrettyChars());
   61             return true;
   62         }
   63     }
   64 
   65     bool result = false;
   66     for (size_t i = iStart; i < ad.fields.dim; i++)
   67     {
   68         VarDeclaration vd = ad.fields[i];
   69         Type tb = vd.type.baseElemOf();
   70         if (tb.ty == Tstruct)
   71         {
   72             result |= checkFrameAccess(loc, sc, (cast(TypeStruct)tb).sym);
   73         }
   74     }
   75     return result;
   76 }
   77 
   78 /***********************************************
   79  * Mark variable v as modified if it is inside a constructor that var
   80  * is a field in.
   81  */
   82 bool modifyFieldVar(Loc loc, Scope* sc, VarDeclaration var, Expression e1)
   83 {
   84     //printf("modifyFieldVar(var = %s)\n", var.toChars());
   85     Dsymbol s = sc.func;
   86     while (1)
   87     {
   88         FuncDeclaration fd = null;
   89         if (s)
   90             fd = s.isFuncDeclaration();
   91         if (fd &&
   92             ((var.isField() && (fd.isCtorDeclaration() || fd.isPostBlitDeclaration())) ||
   93              (!var.isField() && fd.isStaticCtorDeclaration())) &&
   94             fd.toParentDecl() == var.toParent2() &&
   95             (!e1 || e1.op == TOK.this_))
   96         {
   97             bool result = true;
   98 
   99             if (!fd.isPostBlitDeclaration())
  100             {
  101                 var.ctorinit = true;
  102                 //printf("setting ctorinit\n");
  103             }
  104 
  105             if (var.isField() && sc.ctorflow.fieldinit.length && !sc.intypeof)
  106             {
  107                 assert(e1);
  108                 auto mustInit = ((var.storage_class & STC.nodefaultctor) != 0 ||
  109                                  var.type.needsNested());
  110 
  111                 const dim = sc.ctorflow.fieldinit.length;
  112                 auto ad = fd.isMemberDecl();
  113                 assert(ad);
  114                 size_t i;
  115                 for (i = 0; i < dim; i++) // same as findFieldIndexByName in ctfeexp.c ?
  116                 {
  117                     if (ad.fields[i] == var)
  118                         break;
  119                 }
  120                 assert(i < dim);
  121                 auto fieldInit = &sc.ctorflow.fieldinit[i];
  122                 const fi = fieldInit.csx;
  123 
  124                 if (fi & CSX.this_ctor)
  125                 {
  126                     if (var.type.isMutable() && e1.type.isMutable())
  127                         result = false;
  128                     else
  129                     {
  130                         const(char)* modStr = !var.type.isMutable() ? MODtoChars(var.type.mod) : MODtoChars(e1.type.mod);
  131                         .error(loc, "%s field `%s` initialized multiple times", modStr, var.toChars());
  132                         .errorSupplemental(fieldInit.loc, "Previous initialization is here.");
  133                     }
  134                 }
  135                 else if (sc.inLoop || (fi & CSX.label))
  136                 {
  137                     if (!mustInit && var.type.isMutable() && e1.type.isMutable())
  138                         result = false;
  139                     else
  140                     {
  141                         const(char)* modStr = !var.type.isMutable() ? MODtoChars(var.type.mod) : MODtoChars(e1.type.mod);
  142                         .error(loc, "%s field `%s` initialization is not allowed in loops or after labels", modStr, var.toChars());
  143                     }
  144                 }
  145 
  146                 fieldInit.csx |= CSX.this_ctor;
  147                 fieldInit.loc = e1.loc;
  148                 if (var.overlapped) // https://issues.dlang.org/show_bug.cgi?id=15258
  149                 {
  150                     foreach (j, v; ad.fields)
  151                     {
  152                         if (v is var || !var.isOverlappedWith(v))
  153                             continue;
  154                         v.ctorinit = true;
  155                         sc.ctorflow.fieldinit[j].csx = CSX.this_ctor;
  156                     }
  157                 }
  158             }
  159             else if (fd != sc.func)
  160             {
  161                 if (var.type.isMutable())
  162                     result = false;
  163                 else if (sc.func.fes)
  164                 {
  165                     const(char)* p = var.isField() ? "field" : var.kind();
  166                     .error(loc, "%s %s `%s` initialization is not allowed in foreach loop",
  167                         MODtoChars(var.type.mod), p, var.toChars());
  168                 }
  169                 else
  170                 {
  171                     const(char)* p = var.isField() ? "field" : var.kind();
  172                     .error(loc, "%s %s `%s` initialization is not allowed in nested function `%s`",
  173                         MODtoChars(var.type.mod), p, var.toChars(), sc.func.toChars());
  174                 }
  175             }
  176             return result;
  177         }
  178         else
  179         {
  180             if (s)
  181             {
  182                 s = s.toParentP(var.toParent2());
  183                 continue;
  184             }
  185         }
  186         break;
  187     }
  188     return false;
  189 }
  190 
  191 /******************************************
  192  */
  193 extern (C++) void ObjectNotFound(Identifier id)
  194 {
  195     error(Loc.initial, "`%s` not found. object.d may be incorrectly installed or corrupt.", id.toChars());
  196     fatal();
  197 }
  198 
  199 enum STC : ulong
  200 {
  201     undefined_          = 0L,
  202     static_             = (1L << 0),
  203     extern_             = (1L << 1),
  204     const_              = (1L << 2),
  205     final_              = (1L << 3),
  206     abstract_           = (1L << 4),
  207     parameter           = (1L << 5),
  208     field               = (1L << 6),
  209     override_           = (1L << 7),
  210     auto_               = (1L << 8),
  211     synchronized_       = (1L << 9),
  212     deprecated_         = (1L << 10),
  213     in_                 = (1L << 11),   // in parameter
  214     out_                = (1L << 12),   // out parameter
  215     lazy_               = (1L << 13),   // lazy parameter
  216     foreach_            = (1L << 14),   // variable for foreach loop
  217                           //(1L << 15)
  218     variadic            = (1L << 16),   // the 'variadic' parameter in: T foo(T a, U b, V variadic...)
  219     ctorinit            = (1L << 17),   // can only be set inside constructor
  220     templateparameter   = (1L << 18),   // template parameter
  221     scope_              = (1L << 19),
  222     immutable_          = (1L << 20),
  223     ref_                = (1L << 21),
  224     init                = (1L << 22),   // has explicit initializer
  225     manifest            = (1L << 23),   // manifest constant
  226     nodtor              = (1L << 24),   // don't run destructor
  227     nothrow_            = (1L << 25),   // never throws exceptions
  228     pure_               = (1L << 26),   // pure function
  229     tls                 = (1L << 27),   // thread local
  230     alias_              = (1L << 28),   // alias parameter
  231     shared_             = (1L << 29),   // accessible from multiple threads
  232     gshared             = (1L << 30),   // accessible from multiple threads, but not typed as "shared"
  233     wild                = (1L << 31),   // for "wild" type constructor
  234     property            = (1L << 32),
  235     safe                = (1L << 33),
  236     trusted             = (1L << 34),
  237     system              = (1L << 35),
  238     ctfe                = (1L << 36),   // can be used in CTFE, even if it is static
  239     disable             = (1L << 37),   // for functions that are not callable
  240     result              = (1L << 38),   // for result variables passed to out contracts
  241     nodefaultctor       = (1L << 39),   // must be set inside constructor
  242     temp                = (1L << 40),   // temporary variable
  243     rvalue              = (1L << 41),   // force rvalue for variables
  244     nogc                = (1L << 42),   // @nogc
  245     volatile_           = (1L << 43),   // destined for volatile in the back end
  246     return_             = (1L << 44),   // 'return ref' or 'return scope' for function parameters
  247     autoref             = (1L << 45),   // Mark for the already deduced 'auto ref' parameter
  248     inference           = (1L << 46),   // do attribute inference
  249     exptemp             = (1L << 47),   // temporary variable that has lifetime restricted to an expression
  250     maybescope          = (1L << 48),   // parameter might be 'scope'
  251     scopeinferred       = (1L << 49),   // 'scope' has been inferred and should not be part of mangling
  252     future              = (1L << 50),   // introducing new base class function
  253     local               = (1L << 51),   // do not forward (see dmd.dsymbol.ForwardingScopeDsymbol).
  254     returninferred      = (1L << 52),   // 'return' has been inferred and should not be part of mangling
  255     live                = (1L << 53),   // function @live attribute
  256 
  257     // Group members are mutually exclusive (there can be only one)
  258     safeGroup = STC.safe | STC.trusted | STC.system,
  259 
  260     /// Group for `in` / `out` / `ref` storage classes on parameter
  261     IOR  = STC.in_ | STC.ref_ | STC.out_,
  262 
  263     TYPECTOR = (STC.const_ | STC.immutable_ | STC.shared_ | STC.wild),
  264     FUNCATTR = (STC.ref_ | STC.nothrow_ | STC.nogc | STC.pure_ | STC.property | STC.live |
  265                 STC.safeGroup),
  266 }
  267 
  268 enum STCStorageClass =
  269     (STC.auto_ | STC.scope_ | STC.static_ | STC.extern_ | STC.const_ | STC.final_ | STC.abstract_ | STC.synchronized_ |
  270      STC.deprecated_ | STC.future | STC.override_ | STC.lazy_ | STC.alias_ | STC.out_ | STC.in_ | STC.manifest |
  271      STC.immutable_ | STC.shared_ | STC.wild | STC.nothrow_ | STC.nogc | STC.pure_ | STC.ref_ | STC.return_ | STC.tls | STC.gshared |
  272      STC.property | STC.safeGroup | STC.disable | STC.local | STC.live);
  273 
  274 /* These storage classes "flow through" to the inner scope of a Dsymbol
  275  */
  276 enum STCFlowThruAggregate = STC.safeGroup;    /// for an AggregateDeclaration
  277 enum STCFlowThruFunction = ~(STC.auto_ | STC.scope_ | STC.static_ | STC.extern_ | STC.abstract_ | STC.deprecated_ | STC.override_ |
  278                          STC.TYPECTOR | STC.final_ | STC.tls | STC.gshared | STC.ref_ | STC.return_ | STC.property |
  279                          STC.nothrow_ | STC.pure_ | STC.safe | STC.trusted | STC.system); /// for a FuncDeclaration
  280 
  281 /* Accumulator for successive matches.
  282  */
  283 struct MatchAccumulator
  284 {
  285     int count;              // number of matches found so far
  286     MATCH last = MATCH.nomatch; // match level of lastf
  287     FuncDeclaration lastf;  // last matching function we found
  288     FuncDeclaration nextf;  // if ambiguous match, this is the "other" function
  289 }
  290 
  291 /***********************************************************
  292  */
  293 extern (C++) abstract class Declaration : Dsymbol
  294 {
  295     Type type;
  296     Type originalType;  // before semantic analysis
  297     StorageClass storage_class = STC.undefined_;
  298     Prot protection;
  299     LINK linkage = LINK.default_;
  300     int inuse;          // used to detect cycles
  301 
  302     // overridden symbol with pragma(mangle, "...")
  303     const(char)[] mangleOverride;
  304 
  305     final extern (D) this(Identifier ident)
  306     {
  307         super(ident);
  308         protection = Prot(Prot.Kind.undefined);
  309     }
  310 
  311     final extern (D) this(const ref Loc loc, Identifier ident)
  312     {
  313         super(loc, ident);
  314         protection = Prot(Prot.Kind.undefined);
  315     }
  316 
  317     override const(char)* kind() const
  318     {
  319         return "declaration";
  320     }
  321 
  322     override final d_uns64 size(const ref Loc loc)
  323     {
  324         assert(type);
  325         return type.size();
  326     }
  327 
  328     /**
  329      * Issue an error if an attempt to call a disabled method is made
  330      *
  331      * If the declaration is disabled but inside a disabled function,
  332      * returns `true` but do not issue an error message.
  333      *
  334      * Params:
  335      *   loc = Location information of the call
  336      *   sc  = Scope in which the call occurs
  337      *   isAliasedDeclaration = if `true` searches overload set
  338      *
  339      * Returns:
  340      *   `true` if this `Declaration` is `@disable`d, `false` otherwise.
  341      */
  342     extern (D) final bool checkDisabled(Loc loc, Scope* sc, bool isAliasedDeclaration = false)
  343     {
  344         if (storage_class & STC.disable)
  345         {
  346             if (!(sc.func && sc.func.storage_class & STC.disable))
  347             {
  348                 auto p = toParent();
  349                 if (p && isPostBlitDeclaration())
  350                     p.error(loc, "is not copyable because it is annotated with `@disable`");
  351                 else
  352                 {
  353                     // if the function is @disabled, maybe there
  354                     // is an overload in the overload set that isn't
  355                     if (isAliasedDeclaration)
  356                     {
  357                         FuncDeclaration fd = isFuncDeclaration();
  358                         if (fd)
  359                         {
  360                             for (FuncDeclaration ovl = fd; ovl; ovl = cast(FuncDeclaration)ovl.overnext)
  361                                 if (!(ovl.storage_class & STC.disable))
  362                                     return false;
  363                         }
  364                     }
  365                     error(loc, "cannot be used because it is annotated with `@disable`");
  366                 }
  367             }
  368             return true;
  369         }
  370 
  371         return false;
  372     }
  373 
  374     /*************************************
  375      * Check to see if declaration can be modified in this context (sc).
  376      * Issue error if not.
  377      * Params:
  378      *  loc  = location for error messages
  379      *  e1   = `null` or `this` expression when this declaration is a field
  380      *  sc   = context
  381      *  flag = !=0 means do not issue error message for invalid modification
  382      * Returns:
  383      *  Modifiable.yes or Modifiable.initialization
  384      */
  385     extern (D) final Modifiable checkModify(Loc loc, Scope* sc, Expression e1, int flag)
  386     {
  387         VarDeclaration v = isVarDeclaration();
  388         if (v && v.canassign)
  389             return Modifiable.initialization;
  390 
  391         if (isParameter() || isResult())
  392         {
  393             for (Scope* scx = sc; scx; scx = scx.enclosing)
  394             {
  395                 if (scx.func == parent && (scx.flags & SCOPE.contract))
  396                 {
  397                     const(char)* s = isParameter() && parent.ident != Id.ensure ? "parameter" : "result";
  398                     if (!flag)
  399                         error(loc, "cannot modify %s `%s` in contract", s, toChars());
  400                     return Modifiable.initialization; // do not report type related errors
  401                 }
  402             }
  403         }
  404 
  405         if (e1 && e1.op == TOK.this_ && isField())
  406         {
  407             VarDeclaration vthis = (cast(ThisExp)e1).var;
  408             for (Scope* scx = sc; scx; scx = scx.enclosing)
  409             {
  410                 if (scx.func == vthis.parent && (scx.flags & SCOPE.contract))
  411                 {
  412                     if (!flag)
  413                         error(loc, "cannot modify parameter 'this' in contract");
  414                     return Modifiable.initialization; // do not report type related errors
  415                 }
  416             }
  417         }
  418 
  419         if (v && (isCtorinit() || isField()))
  420         {
  421             // It's only modifiable if inside the right constructor
  422             if ((storage_class & (STC.foreach_ | STC.ref_)) == (STC.foreach_ | STC.ref_))
  423                 return Modifiable.initialization;
  424             return modifyFieldVar(loc, sc, v, e1)
  425                 ? Modifiable.initialization : Modifiable.yes;
  426         }
  427         return Modifiable.yes;
  428     }
  429 
  430     override final Dsymbol search(const ref Loc loc, Identifier ident, int flags = SearchLocalsOnly)
  431     {
  432         Dsymbol s = Dsymbol.search(loc, ident, flags);
  433         if (!s && type)
  434         {
  435             s = type.toDsymbol(_scope);
  436             if (s)
  437                 s = s.search(loc, ident, flags);
  438         }
  439         return s;
  440     }
  441 
  442     final bool isStatic() const pure nothrow @nogc @safe
  443     {
  444         return (storage_class & STC.static_) != 0;
  445     }
  446 
  447     bool isDelete()
  448     {
  449         return false;
  450     }
  451 
  452     bool isDataseg()
  453     {
  454         return false;
  455     }
  456 
  457     bool isThreadlocal()
  458     {
  459         return false;
  460     }
  461 
  462     bool isCodeseg() const pure nothrow @nogc @safe
  463     {
  464         return false;
  465     }
  466 
  467     final bool isCtorinit() const pure nothrow @nogc @safe
  468     {
  469         return (storage_class & STC.ctorinit) != 0;
  470     }
  471 
  472     final bool isFinal() const pure nothrow @nogc @safe
  473     {
  474         return (storage_class & STC.final_) != 0;
  475     }
  476 
  477     bool isAbstract()
  478     {
  479         return (storage_class & STC.abstract_) != 0;
  480     }
  481 
  482     final bool isConst() const pure nothrow @nogc @safe
  483     {
  484         return (storage_class & STC.const_) != 0;
  485     }
  486 
  487     final bool isImmutable() const pure nothrow @nogc @safe
  488     {
  489         return (storage_class & STC.immutable_) != 0;
  490     }
  491 
  492     final bool isWild() const pure nothrow @nogc @safe
  493     {
  494         return (storage_class & STC.wild) != 0;
  495     }
  496 
  497     final bool isAuto() const pure nothrow @nogc @safe
  498     {
  499         return (storage_class & STC.auto_) != 0;
  500     }
  501 
  502     final bool isScope() const pure nothrow @nogc @safe
  503     {
  504         return (storage_class & STC.scope_) != 0;
  505     }
  506 
  507     final bool isSynchronized() const pure nothrow @nogc @safe
  508     {
  509         return (storage_class & STC.synchronized_) != 0;
  510     }
  511 
  512     final bool isParameter() const pure nothrow @nogc @safe
  513     {
  514         return (storage_class & STC.parameter) != 0;
  515     }
  516 
  517     override final bool isDeprecated() const pure nothrow @nogc @safe
  518     {
  519         return (storage_class & STC.deprecated_) != 0;
  520     }
  521 
  522     final bool isDisabled() const pure nothrow @nogc @safe
  523     {
  524         return (storage_class & STC.disable) != 0;
  525     }
  526 
  527     final bool isOverride() const pure nothrow @nogc @safe
  528     {
  529         return (storage_class & STC.override_) != 0;
  530     }
  531 
  532     final bool isResult() const pure nothrow @nogc @safe
  533     {
  534         return (storage_class & STC.result) != 0;
  535     }
  536 
  537     final bool isField() const pure nothrow @nogc @safe
  538     {
  539         return (storage_class & STC.field) != 0;
  540     }
  541 
  542     final bool isIn() const pure nothrow @nogc @safe
  543     {
  544         return (storage_class & STC.in_) != 0;
  545     }
  546 
  547     final bool isOut() const pure nothrow @nogc @safe
  548     {
  549         return (storage_class & STC.out_) != 0;
  550     }
  551 
  552     final bool isRef() const pure nothrow @nogc @safe
  553     {
  554         return (storage_class & STC.ref_) != 0;
  555     }
  556 
  557     final bool isFuture() const pure nothrow @nogc @safe
  558     {
  559         return (storage_class & STC.future) != 0;
  560     }
  561 
  562     override final Prot prot() pure nothrow @nogc @safe
  563     {
  564         return protection;
  565     }
  566 
  567     override final inout(Declaration) isDeclaration() inout
  568     {
  569         return this;
  570     }
  571 
  572     override void accept(Visitor v)
  573     {
  574         v.visit(this);
  575     }
  576 }
  577 
  578 /***********************************************************
  579  */
  580 extern (C++) final class TupleDeclaration : Declaration
  581 {
  582     Objects* objects;
  583     bool isexp;             // true: expression tuple
  584     TypeTuple tupletype;    // !=null if this is a type tuple
  585 
  586     extern (D) this(const ref Loc loc, Identifier ident, Objects* objects)
  587     {
  588         super(loc, ident);
  589         this.objects = objects;
  590     }
  591 
  592     override Dsymbol syntaxCopy(Dsymbol s)
  593     {
  594         assert(0);
  595     }
  596 
  597     override const(char)* kind() const
  598     {
  599         return "tuple";
  600     }
  601 
  602     override Type getType()
  603     {
  604         /* If this tuple represents a type, return that type
  605          */
  606 
  607         //printf("TupleDeclaration::getType() %s\n", toChars());
  608         if (isexp)
  609             return null;
  610         if (!tupletype)
  611         {
  612             /* It's only a type tuple if all the Object's are types
  613              */
  614             for (size_t i = 0; i < objects.dim; i++)
  615             {
  616                 RootObject o = (*objects)[i];
  617                 if (o.dyncast() != DYNCAST.type)
  618                 {
  619                     //printf("\tnot[%d], %p, %d\n", i, o, o.dyncast());
  620                     return null;
  621                 }
  622             }
  623 
  624             /* We know it's a type tuple, so build the TypeTuple
  625              */
  626             Types* types = cast(Types*)objects;
  627             auto args = new Parameters(objects.dim);
  628             OutBuffer buf;
  629             int hasdeco = 1;
  630             for (size_t i = 0; i < types.dim; i++)
  631             {
  632                 Type t = (*types)[i];
  633                 //printf("type = %s\n", t.toChars());
  634                 version (none)
  635                 {
  636                     buf.printf("_%s_%d", ident.toChars(), i);
  637                     const len = buf.offset;
  638                     const name = buf.extractSlice().ptr;
  639                     auto id = Identifier.idPool(name, len);
  640                     auto arg = new Parameter(STC.in_, t, id, null);
  641                 }
  642                 else
  643                 {
  644                     auto arg = new Parameter(0, t, null, null, null);
  645                 }
  646                 (*args)[i] = arg;
  647                 if (!t.deco)
  648                     hasdeco = 0;
  649             }
  650 
  651             tupletype = new TypeTuple(args);
  652             if (hasdeco)
  653                 return tupletype.typeSemantic(Loc.initial, null);
  654         }
  655         return tupletype;
  656     }
  657 
  658     override Dsymbol toAlias2()
  659     {
  660         //printf("TupleDeclaration::toAlias2() '%s' objects = %s\n", toChars(), objects.toChars());
  661         for (size_t i = 0; i < objects.dim; i++)
  662         {
  663             RootObject o = (*objects)[i];
  664             if (Dsymbol s = isDsymbol(o))
  665             {
  666                 s = s.toAlias2();
  667                 (*objects)[i] = s;
  668             }
  669         }
  670         return this;
  671     }
  672 
  673     override bool needThis()
  674     {
  675         //printf("TupleDeclaration::needThis(%s)\n", toChars());
  676         for (size_t i = 0; i < objects.dim; i++)
  677         {
  678             RootObject o = (*objects)[i];
  679             if (o.dyncast() == DYNCAST.expression)
  680             {
  681                 Expression e = cast(Expression)o;
  682                 if (e.op == TOK.dSymbol)
  683                 {
  684                     DsymbolExp ve = cast(DsymbolExp)e;
  685                     Declaration d = ve.s.isDeclaration();
  686                     if (d && d.needThis())
  687                     {
  688                         return true;
  689                     }
  690                 }
  691             }
  692         }
  693         return false;
  694     }
  695 
  696     override inout(TupleDeclaration) isTupleDeclaration() inout
  697     {
  698         return this;
  699     }
  700 
  701     override void accept(Visitor v)
  702     {
  703         v.visit(this);
  704     }
  705 }
  706 
  707 /***********************************************************
  708  */
  709 extern (C++) final class AliasDeclaration : Declaration
  710 {
  711     Dsymbol aliassym;
  712     Dsymbol overnext;   // next in overload list
  713     Dsymbol _import;    // !=null if unresolved internal alias for selective import
  714 
  715     extern (D) this(const ref Loc loc, Identifier ident, Type type)
  716     {
  717         super(loc, ident);
  718         //printf("AliasDeclaration(id = '%s', type = %p)\n", id.toChars(), type);
  719         //printf("type = '%s'\n", type.toChars());
  720         this.type = type;
  721         assert(type);
  722     }
  723 
  724     extern (D) this(const ref Loc loc, Identifier ident, Dsymbol s)
  725     {
  726         super(loc, ident);
  727         //printf("AliasDeclaration(id = '%s', s = %p)\n", id.toChars(), s);
  728         assert(s != this);
  729         this.aliassym = s;
  730         assert(s);
  731     }
  732 
  733     static AliasDeclaration create(Loc loc, Identifier id, Type type)
  734     {
  735         return new AliasDeclaration(loc, id, type);
  736     }
  737 
  738     override Dsymbol syntaxCopy(Dsymbol s)
  739     {
  740         //printf("AliasDeclaration::syntaxCopy()\n");
  741         assert(!s);
  742         AliasDeclaration sa = type ? new AliasDeclaration(loc, ident, type.syntaxCopy()) : new AliasDeclaration(loc, ident, aliassym.syntaxCopy(null));
  743         sa.comment = comment;
  744         sa.storage_class = storage_class;
  745         return sa;
  746     }
  747 
  748     override bool overloadInsert(Dsymbol s)
  749     {
  750         //printf("[%s] AliasDeclaration::overloadInsert('%s') s = %s %s @ [%s]\n",
  751         //       loc.toChars(), toChars(), s.kind(), s.toChars(), s.loc.toChars());
  752 
  753         /** Aliases aren't overloadable themselves, but if their Aliasee is
  754          *  overloadable they are converted to an overloadable Alias (either
  755          *  FuncAliasDeclaration or OverDeclaration).
  756          *
  757          *  This is done by moving the Aliasee into such an overloadable alias
  758          *  which is then used to replace the existing Aliasee. The original
  759          *  Alias (_this_) remains a useless shell.
  760          *
  761          *  This is a horrible mess. It was probably done to avoid replacing
  762          *  existing AST nodes and references, but it needs a major
  763          *  simplification b/c it's too complex to maintain.
  764          *
  765          *  A simpler approach might be to merge any colliding symbols into a
  766          *  simple Overload class (an array) and then later have that resolve
  767          *  all collisions.
  768          */
  769         if (semanticRun >= PASS.semanticdone)
  770         {
  771             /* Semantic analysis is already finished, and the aliased entity
  772              * is not overloadable.
  773              */
  774             if (type)
  775                 return false;
  776 
  777             /* When s is added in member scope by static if, mixin("code") or others,
  778              * aliassym is determined already. See the case in: test/compilable/test61.d
  779              */
  780             auto sa = aliassym.toAlias();
  781             if (auto fd = sa.isFuncDeclaration())
  782             {
  783                 auto fa = new FuncAliasDeclaration(ident, fd);
  784                 fa.protection = protection;
  785                 fa.parent = parent;
  786                 aliassym = fa;
  787                 return aliassym.overloadInsert(s);
  788             }
  789             if (auto td = sa.isTemplateDeclaration())
  790             {
  791                 auto od = new OverDeclaration(ident, td);
  792                 od.protection = protection;
  793                 od.parent = parent;
  794                 aliassym = od;
  795                 return aliassym.overloadInsert(s);
  796             }
  797             if (auto od = sa.isOverDeclaration())
  798             {
  799                 if (sa.ident != ident || sa.parent != parent)
  800                 {
  801                     od = new OverDeclaration(ident, od);
  802                     od.protection = protection;
  803                     od.parent = parent;
  804                     aliassym = od;
  805                 }
  806                 return od.overloadInsert(s);
  807             }
  808             if (auto os = sa.isOverloadSet())
  809             {
  810                 if (sa.ident != ident || sa.parent != parent)
  811                 {
  812                     os = new OverloadSet(ident, os);
  813                     // TODO: protection is lost here b/c OverloadSets have no protection attribute
  814                     // Might no be a practical issue, b/c the code below fails to resolve the overload anyhow.
  815                     // ----
  816                     // module os1;
  817                     // import a, b;
  818                     // private alias merged = foo; // private alias to overload set of a.foo and b.foo
  819                     // ----
  820                     // module os2;
  821                     // import a, b;
  822                     // public alias merged = bar; // public alias to overload set of a.bar and b.bar
  823                     // ----
  824                     // module bug;
  825                     // import os1, os2;
  826                     // void test() { merged(123); } // should only look at os2.merged
  827                     //
  828                     // os.protection = protection;
  829                     os.parent = parent;
  830                     aliassym = os;
  831                 }
  832                 os.push(s);
  833                 return true;
  834             }
  835             return false;
  836         }
  837 
  838         /* Don't know yet what the aliased symbol is, so assume it can
  839          * be overloaded and check later for correctness.
  840          */
  841         if (overnext)
  842             return overnext.overloadInsert(s);
  843         if (s is this)
  844             return true;
  845         overnext = s;
  846         return true;
  847     }
  848 
  849     override const(char)* kind() const
  850     {
  851         return "alias";
  852     }
  853 
  854     override Type getType()
  855     {
  856         if (type)
  857             return type;
  858         return toAlias().getType();
  859     }
  860 
  861     override Dsymbol toAlias()
  862     {
  863         //printf("[%s] AliasDeclaration::toAlias('%s', this = %p, aliassym = %p, kind = '%s', inuse = %d)\n",
  864         //    loc.toChars(), toChars(), this, aliassym, aliassym ? aliassym.kind() : "", inuse);
  865         assert(this != aliassym);
  866         //static int count; if (++count == 10) *(char*)0=0;
  867         if (inuse == 1 && type && _scope)
  868         {
  869             inuse = 2;
  870             uint olderrors = global.errors;
  871             Dsymbol s = type.toDsymbol(_scope);
  872             //printf("[%s] type = %s, s = %p, this = %p\n", loc.toChars(), type.toChars(), s, this);
  873             if (global.errors != olderrors)
  874                 goto Lerr;
  875             if (s)
  876             {
  877                 s = s.toAlias();
  878                 if (global.errors != olderrors)
  879                     goto Lerr;
  880                 aliassym = s;
  881                 inuse = 0;
  882             }
  883             else
  884             {
  885                 Type t = type.typeSemantic(loc, _scope);
  886                 if (t.ty == Terror)
  887                     goto Lerr;
  888                 if (global.errors != olderrors)
  889                     goto Lerr;
  890                 //printf("t = %s\n", t.toChars());
  891                 inuse = 0;
  892             }
  893         }
  894         if (inuse)
  895         {
  896             error("recursive alias declaration");
  897 
  898         Lerr:
  899             // Avoid breaking "recursive alias" state during errors gagged
  900             if (global.gag)
  901                 return this;
  902             aliassym = new AliasDeclaration(loc, ident, Type.terror);
  903             type = Type.terror;
  904             return aliassym;
  905         }
  906 
  907         if (semanticRun >= PASS.semanticdone)
  908         {
  909             // semantic is already done.
  910 
  911             // Do not see aliassym !is null, because of lambda aliases.
  912 
  913             // Do not see type.deco !is null, even so "alias T = const int;` needs
  914             // semantic analysis to take the storage class `const` as type qualifier.
  915         }
  916         else
  917         {
  918             if (_import && _import._scope)
  919             {
  920                 /* If this is an internal alias for selective/renamed import,
  921                  * load the module first.
  922                  */
  923                 _import.dsymbolSemantic(null);
  924             }
  925             if (_scope)
  926             {
  927                 aliasSemantic(this, _scope);
  928             }
  929         }
  930 
  931         inuse = 1;
  932         Dsymbol s = aliassym ? aliassym.toAlias() : this;
  933         inuse = 0;
  934         return s;
  935     }
  936 
  937     override Dsymbol toAlias2()
  938     {
  939         if (inuse)
  940         {
  941             error("recursive alias declaration");
  942             return this;
  943         }
  944         inuse = 1;
  945         Dsymbol s = aliassym ? aliassym.toAlias2() : this;
  946         inuse = 0;
  947         return s;
  948     }
  949 
  950     override bool isOverloadable() const
  951     {
  952         // assume overloadable until alias is resolved
  953         return semanticRun < PASS.semanticdone ||
  954             aliassym && aliassym.isOverloadable();
  955     }
  956 
  957     override inout(AliasDeclaration) isAliasDeclaration() inout
  958     {
  959         return this;
  960     }
  961 
  962     /** Returns: `true` if this instance was created to make a template parameter
  963     visible in the scope of a template body, `false` otherwise */
  964     extern (D) bool isAliasedTemplateParameter() const
  965     {
  966         return !!(storage_class & STC.templateparameter);
  967     }
  968 
  969     override void accept(Visitor v)
  970     {
  971         v.visit(this);
  972     }
  973 }
  974 
  975 /***********************************************************
  976  */
  977 extern (C++) final class OverDeclaration : Declaration
  978 {
  979     Dsymbol overnext;   // next in overload list
  980     Dsymbol aliassym;
  981     bool hasOverloads;
  982 
  983     extern (D) this(Identifier ident, Dsymbol s, bool hasOverloads = true)
  984     {
  985         super(ident);
  986         this.aliassym = s;
  987         this.hasOverloads = hasOverloads;
  988         if (hasOverloads)
  989         {
  990             if (OverDeclaration od = aliassym.isOverDeclaration())
  991                 this.hasOverloads = od.hasOverloads;
  992         }
  993         else
  994         {
  995             // for internal use
  996             assert(!aliassym.isOverDeclaration());
  997         }
  998     }
  999 
 1000     override const(char)* kind() const
 1001     {
 1002         return "overload alias"; // todo
 1003     }
 1004 
 1005     override bool equals(const RootObject o) const
 1006     {
 1007         if (this == o)
 1008             return true;
 1009 
 1010         auto s = isDsymbol(o);
 1011         if (!s)
 1012             return false;
 1013 
 1014         auto od1 = this;
 1015         if (auto od2 = s.isOverDeclaration())
 1016         {
 1017             return od1.aliassym.equals(od2.aliassym) && od1.hasOverloads == od2.hasOverloads;
 1018         }
 1019         if (aliassym == s)
 1020         {
 1021             if (hasOverloads)
 1022                 return true;
 1023             if (auto fd = s.isFuncDeclaration())
 1024             {
 1025                 return fd.isUnique();
 1026             }
 1027             if (auto td = s.isTemplateDeclaration())
 1028             {
 1029                 return td.overnext is null;
 1030             }
 1031         }
 1032         return false;
 1033     }
 1034 
 1035     override bool overloadInsert(Dsymbol s)
 1036     {
 1037         //printf("OverDeclaration::overloadInsert('%s') aliassym = %p, overnext = %p\n", s.toChars(), aliassym, overnext);
 1038         if (overnext)
 1039             return overnext.overloadInsert(s);
 1040         if (s == this)
 1041             return true;
 1042         overnext = s;
 1043         return true;
 1044     }
 1045 
 1046     override bool isOverloadable() const
 1047     {
 1048         return true;
 1049     }
 1050 
 1051     Dsymbol isUnique()
 1052     {
 1053         if (!hasOverloads)
 1054         {
 1055             if (aliassym.isFuncDeclaration() ||
 1056                 aliassym.isTemplateDeclaration())
 1057             {
 1058                 return aliassym;
 1059             }
 1060         }
 1061 
 1062         Dsymbol result = null;
 1063         overloadApply(aliassym, (Dsymbol s)
 1064         {
 1065             if (result)
 1066             {
 1067                 result = null;
 1068                 return 1; // ambiguous, done
 1069             }
 1070             else
 1071             {
 1072                 result = s;
 1073                 return 0;
 1074             }
 1075         });
 1076         return result;
 1077     }
 1078 
 1079     override inout(OverDeclaration) isOverDeclaration() inout
 1080     {
 1081         return this;
 1082     }
 1083 
 1084     override void accept(Visitor v)
 1085     {
 1086         v.visit(this);
 1087     }
 1088 }
 1089 
 1090 /***********************************************************
 1091  */
 1092 extern (C++) class VarDeclaration : Declaration
 1093 {
 1094     Initializer _init;
 1095     uint offset;
 1096     uint sequenceNumber;            // order the variables are declared
 1097     __gshared uint nextSequenceNumber;   // the counter for sequenceNumber
 1098     FuncDeclarations nestedrefs;    // referenced by these lexically nested functions
 1099     structalign_t alignment;
 1100     bool isargptr;                  // if parameter that _argptr points to
 1101     bool ctorinit;                  // it has been initialized in a ctor
 1102     bool iscatchvar;                // this is the exception object variable in catch() clause
 1103     bool isowner;                   // this is an Owner, despite it being `scope`
 1104 
 1105     // Both these mean the var is not rebindable once assigned,
 1106     // and the destructor gets run when it goes out of scope
 1107     bool onstack;                   // it is a class that was allocated on the stack
 1108     bool mynew;                     // it is a class new'd with custom operator new
 1109 
 1110     byte canassign;                  // it can be assigned to
 1111     bool overlapped;                // if it is a field and has overlapping
 1112     bool overlapUnsafe;             // if it is an overlapping field and the overlaps are unsafe
 1113     bool doNotInferScope;           // do not infer 'scope' for this variable
 1114     bool doNotInferReturn;          // do not infer 'return' for this variable
 1115     ubyte isdataseg;                // private data for isDataseg 0 unset, 1 true, 2 false
 1116     Dsymbol aliassym;               // if redone as alias to another symbol
 1117     VarDeclaration lastVar;         // Linked list of variables for goto-skips-init detection
 1118     uint endlinnum;                 // line number of end of scope that this var lives in
 1119 
 1120     // When interpreting, these point to the value (NULL if value not determinable)
 1121     // The index of this variable on the CTFE stack, AdrOnStackNone if not allocated
 1122     enum AdrOnStackNone = ~0u;
 1123     uint ctfeAdrOnStack;
 1124 
 1125     Expression edtor;               // if !=null, does the destruction of the variable
 1126     IntRange* range;                // if !=null, the variable is known to be within the range
 1127 
 1128     VarDeclarations* maybes;        // STC.maybescope variables that are assigned to this STC.maybescope variable
 1129 
 1130     final extern (D) this(const ref Loc loc, Type type, Identifier ident, Initializer _init, StorageClass storage_class = STC.undefined_)
 1131     in
 1132     {
 1133         assert(ident);
 1134     }
 1135     do
 1136     {
 1137         //printf("VarDeclaration('%s')\n", ident.toChars());
 1138         super(loc, ident);
 1139         debug
 1140         {
 1141             if (!type && !_init)
 1142             {
 1143                 //printf("VarDeclaration('%s')\n", ident.toChars());
 1144                 //*(char*)0=0;
 1145             }
 1146         }
 1147 
 1148         assert(type || _init);
 1149         this.type = type;
 1150         this._init = _init;
 1151         ctfeAdrOnStack = AdrOnStackNone;
 1152         this.storage_class = storage_class;
 1153         sequenceNumber = ++nextSequenceNumber;
 1154     }
 1155 
 1156     static VarDeclaration create(const ref Loc loc, Type type, Identifier ident, Initializer _init, StorageClass storage_class = STC.undefined_)
 1157     {
 1158         return new VarDeclaration(loc, type, ident, _init, storage_class);
 1159     }
 1160 
 1161     override Dsymbol syntaxCopy(Dsymbol s)
 1162     {
 1163         //printf("VarDeclaration::syntaxCopy(%s)\n", toChars());
 1164         assert(!s);
 1165         auto v = new VarDeclaration(loc, type ? type.syntaxCopy() : null, ident, _init ? _init.syntaxCopy() : null, storage_class);
 1166         v.comment = comment;
 1167         return v;
 1168     }
 1169 
 1170     override final void setFieldOffset(AggregateDeclaration ad, uint* poffset, bool isunion)
 1171     {
 1172         //printf("VarDeclaration::setFieldOffset(ad = %s) %s\n", ad.toChars(), toChars());
 1173 
 1174         if (aliassym)
 1175         {
 1176             // If this variable was really a tuple, set the offsets for the tuple fields
 1177             TupleDeclaration v2 = aliassym.isTupleDeclaration();
 1178             assert(v2);
 1179             for (size_t i = 0; i < v2.objects.dim; i++)
 1180             {
 1181                 RootObject o = (*v2.objects)[i];
 1182                 assert(o.dyncast() == DYNCAST.expression);
 1183                 Expression e = cast(Expression)o;
 1184                 assert(e.op == TOK.dSymbol);
 1185                 DsymbolExp se = cast(DsymbolExp)e;
 1186                 se.s.setFieldOffset(ad, poffset, isunion);
 1187             }
 1188             return;
 1189         }
 1190 
 1191         if (!isField())
 1192             return;
 1193         assert(!(storage_class & (STC.static_ | STC.extern_ | STC.parameter | STC.tls)));
 1194 
 1195         //printf("+VarDeclaration::setFieldOffset(ad = %s) %s\n", ad.toChars(), toChars());
 1196 
 1197         /* Fields that are tuples appear both as part of TupleDeclarations and
 1198          * as members. That means ignore them if they are already a field.
 1199          */
 1200         if (offset)
 1201         {
 1202             // already a field
 1203             *poffset = ad.structsize; // https://issues.dlang.org/show_bug.cgi?id=13613
 1204             return;
 1205         }
 1206         for (size_t i = 0; i < ad.fields.dim; i++)
 1207         {
 1208             if (ad.fields[i] == this)
 1209             {
 1210                 // already a field
 1211                 *poffset = ad.structsize; // https://issues.dlang.org/show_bug.cgi?id=13613
 1212                 return;
 1213             }
 1214         }
 1215 
 1216         // Check for forward referenced types which will fail the size() call
 1217         Type t = type.toBasetype();
 1218         if (storage_class & STC.ref_)
 1219         {
 1220             // References are the size of a pointer
 1221             t = Type.tvoidptr;
 1222         }
 1223         Type tv = t.baseElemOf();
 1224         if (tv.ty == Tstruct)
 1225         {
 1226             auto ts = cast(TypeStruct)tv;
 1227             assert(ts.sym != ad);   // already checked in ad.determineFields()
 1228             if (!ts.sym.determineSize(loc))
 1229             {
 1230                 type = Type.terror;
 1231                 errors = true;
 1232                 return;
 1233             }
 1234         }
 1235 
 1236         // List in ad.fields. Even if the type is error, it's necessary to avoid
 1237         // pointless error diagnostic "more initializers than fields" on struct literal.
 1238         ad.fields.push(this);
 1239 
 1240         if (t.ty == Terror)
 1241             return;
 1242 
 1243         const sz = t.size(loc);
 1244         assert(sz != SIZE_INVALID && sz < uint.max);
 1245         uint memsize = cast(uint)sz;                // size of member
 1246         uint memalignsize = target.fieldalign(t);   // size of member for alignment purposes
 1247         offset = AggregateDeclaration.placeField(
 1248             poffset,
 1249             memsize, memalignsize, alignment,
 1250             &ad.structsize, &ad.alignsize,
 1251             isunion);
 1252 
 1253         //printf("\t%s: memalignsize = %d\n", toChars(), memalignsize);
 1254         //printf(" addField '%s' to '%s' at offset %d, size = %d\n", toChars(), ad.toChars(), offset, memsize);
 1255     }
 1256 
 1257     override const(char)* kind() const
 1258     {
 1259         return "variable";
 1260     }
 1261 
 1262     override final inout(AggregateDeclaration) isThis() inout
 1263     {
 1264         if (!(storage_class & (STC.static_ | STC.extern_ | STC.manifest | STC.templateparameter | STC.tls | STC.gshared | STC.ctfe)))
 1265         {
 1266             /* The casting is necessary because `s = s.parent` is otherwise rejected
 1267              */
 1268             for (auto s = cast(Dsymbol)this; s; s = s.parent)
 1269             {
 1270                 auto ad = (cast(inout)s).isMember();
 1271                 if (ad)
 1272                     return ad;
 1273                 if (!s.parent || !s.parent.isTemplateMixin())
 1274                     break;
 1275             }
 1276         }
 1277         return null;
 1278     }
 1279 
 1280     override final bool needThis()
 1281     {
 1282         //printf("VarDeclaration::needThis(%s, x%x)\n", toChars(), storage_class);
 1283         return isField();
 1284     }
 1285 
 1286     override final bool isExport() const
 1287     {
 1288         return protection.kind == Prot.Kind.export_;
 1289     }
 1290 
 1291     override final bool isImportedSymbol() const
 1292     {
 1293         if (protection.kind == Prot.Kind.export_ && !_init && (storage_class & STC.static_ || parent.isModule()))
 1294             return true;
 1295         return false;
 1296     }
 1297 
 1298     /*******************************
 1299      * Does symbol go into data segment?
 1300      * Includes extern variables.
 1301      */
 1302     override final bool isDataseg()
 1303     {
 1304         version (none)
 1305         {
 1306             printf("VarDeclaration::isDataseg(%p, '%s')\n", this, toChars());
 1307             printf("%llx, isModule: %p, isTemplateInstance: %p, isNspace: %p\n",
 1308                    storage_class & (STC.static_ | STC.const_), parent.isModule(), parent.isTemplateInstance(), parent.isNspace());
 1309             printf("parent = '%s'\n", parent.toChars());
 1310         }
 1311 
 1312         if (isdataseg == 0) // the value is not cached
 1313         {
 1314             isdataseg = 2; // The Variables does not go into the datasegment
 1315 
 1316             if (!canTakeAddressOf())
 1317             {
 1318                 return false;
 1319             }
 1320 
 1321             Dsymbol parent = toParent();
 1322             if (!parent && !(storage_class & STC.static_))
 1323             {
 1324                 error("forward referenced");
 1325                 type = Type.terror;
 1326             }
 1327             else if (storage_class & (STC.static_ | STC.extern_ | STC.tls | STC.gshared) ||
 1328                 parent.isModule() || parent.isTemplateInstance() || parent.isNspace())
 1329             {
 1330                 assert(!isParameter() && !isResult());
 1331                 isdataseg = 1; // It is in the DataSegment
 1332             }
 1333         }
 1334 
 1335         return (isdataseg == 1);
 1336     }
 1337     /************************************
 1338      * Does symbol go into thread local storage?
 1339      */
 1340     override final bool isThreadlocal()
 1341     {
 1342         //printf("VarDeclaration::isThreadlocal(%p, '%s')\n", this, toChars());
 1343         /* Data defaults to being thread-local. It is not thread-local
 1344          * if it is immutable, const or shared.
 1345          */
 1346         bool i = isDataseg() && !(storage_class & (STC.immutable_ | STC.const_ | STC.shared_ | STC.gshared));
 1347         //printf("\treturn %d\n", i);
 1348         return i;
 1349     }
 1350 
 1351     /********************************************
 1352      * Can variable be read and written by CTFE?
 1353      */
 1354     final bool isCTFE()
 1355     {
 1356         return (storage_class & STC.ctfe) != 0; // || !isDataseg();
 1357     }
 1358 
 1359     final bool isOverlappedWith(VarDeclaration v)
 1360     {
 1361         const vsz = v.type.size();
 1362         const tsz = type.size();
 1363         assert(vsz != SIZE_INVALID && tsz != SIZE_INVALID);
 1364         return    offset < v.offset + vsz &&
 1365                 v.offset <   offset + tsz;
 1366     }
 1367 
 1368     override final bool hasPointers()
 1369     {
 1370         //printf("VarDeclaration::hasPointers() %s, ty = %d\n", toChars(), type.ty);
 1371         return (!isDataseg() && type.hasPointers());
 1372     }
 1373 
 1374     /*************************************
 1375      * Return true if we can take the address of this variable.
 1376      */
 1377     final bool canTakeAddressOf()
 1378     {
 1379         return !(storage_class & STC.manifest);
 1380     }
 1381 
 1382     /******************************************
 1383      * Return true if variable needs to call the destructor.
 1384      */
 1385     final bool needsScopeDtor()
 1386     {
 1387         //printf("VarDeclaration::needsScopeDtor() %s\n", toChars());
 1388         return edtor && !(storage_class & STC.nodtor);
 1389     }
 1390 
 1391     /******************************************
 1392      * If a variable has a scope destructor call, return call for it.
 1393      * Otherwise, return NULL.
 1394      */
 1395     extern (D) final Expression callScopeDtor(Scope* sc)
 1396     {
 1397         //printf("VarDeclaration::callScopeDtor() %s\n", toChars());
 1398 
 1399         // Destruction of STC.field's is handled by buildDtor()
 1400         if (storage_class & (STC.nodtor | STC.ref_ | STC.out_ | STC.field))
 1401         {
 1402             return null;
 1403         }
 1404 
 1405         if (iscatchvar)
 1406             return null;    // destructor is built by `void semantic(Catch c, Scope* sc)`, not here
 1407 
 1408         Expression e = null;
 1409         // Destructors for structs and arrays of structs
 1410         Type tv = type.baseElemOf();
 1411         if (tv.ty == Tstruct)
 1412         {
 1413             StructDeclaration sd = (cast(TypeStruct)tv).sym;
 1414             if (!sd.dtor || sd.errors)
 1415                 return null;
 1416 
 1417             const sz = type.size();
 1418             assert(sz != SIZE_INVALID);
 1419             if (!sz)
 1420                 return null;
 1421 
 1422             if (type.toBasetype().ty == Tstruct)
 1423             {
 1424                 // v.__xdtor()
 1425                 e = new VarExp(loc, this);
 1426 
 1427                 /* This is a hack so we can call destructors on const/immutable objects.
 1428                  * Need to add things like "const ~this()" and "immutable ~this()" to
 1429                  * fix properly.
 1430                  */
 1431                 e.type = e.type.mutableOf();
 1432 
 1433                 // Enable calling destructors on shared objects.
 1434                 // The destructor is always a single, non-overloaded function,
 1435                 // and must serve both shared and non-shared objects.
 1436                 e.type = e.type.unSharedOf;
 1437 
 1438                 e = new DotVarExp(loc, e, sd.dtor, false);
 1439                 e = new CallExp(loc, e);
 1440             }
 1441             else
 1442             {
 1443                 // __ArrayDtor(v[0 .. n])
 1444                 e = new VarExp(loc, this);
 1445 
 1446                 const sdsz = sd.type.size();
 1447                 assert(sdsz != SIZE_INVALID && sdsz != 0);
 1448                 const n = sz / sdsz;
 1449                 e = new SliceExp(loc, e, new IntegerExp(loc, 0, Type.tsize_t), new IntegerExp(loc, n, Type.tsize_t));
 1450 
 1451                 // Prevent redundant bounds check
 1452                 (cast(SliceExp)e).upperIsInBounds = true;
 1453                 (cast(SliceExp)e).lowerIsLessThanUpper = true;
 1454 
 1455                 // This is a hack so we can call destructors on const/immutable objects.
 1456                 e.type = sd.type.arrayOf();
 1457 
 1458                 e = new CallExp(loc, new IdentifierExp(loc, Id.__ArrayDtor), e);
 1459             }
 1460             return e;
 1461         }
 1462         // Destructors for classes
 1463         if (storage_class & (STC.auto_ | STC.scope_) && !(storage_class & STC.parameter))
 1464         {
 1465             for (ClassDeclaration cd = type.isClassHandle(); cd; cd = cd.baseClass)
 1466             {
 1467                 /* We can do better if there's a way with onstack
 1468                  * classes to determine if there's no way the monitor
 1469                  * could be set.
 1470                  */
 1471                 //if (cd.isInterfaceDeclaration())
 1472                 //    error("interface `%s` cannot be scope", cd.toChars());
 1473 
 1474                 // Destroying C++ scope classes crashes currently. Since C++ class dtors are not currently supported, simply do not run dtors for them.
 1475                 // See https://issues.dlang.org/show_bug.cgi?id=13182
 1476                 if (cd.classKind == ClassKind.cpp)
 1477                 {
 1478                     break;
 1479                 }
 1480                 if (mynew || onstack) // if any destructors
 1481                 {
 1482                     // delete this;
 1483                     Expression ec;
 1484                     ec = new VarExp(loc, this);
 1485                     e = new DeleteExp(loc, ec, true);
 1486                     e.type = Type.tvoid;
 1487                     break;
 1488                 }
 1489             }
 1490         }
 1491         return e;
 1492     }
 1493 
 1494     /*******************************************
 1495      * If variable has a constant expression initializer, get it.
 1496      * Otherwise, return null.
 1497      */
 1498     extern (D) final Expression getConstInitializer(bool needFullType = true)
 1499     {
 1500         assert(type && _init);
 1501 
 1502         // Ungag errors when not speculative
 1503         uint oldgag = global.gag;
 1504         if (global.gag)
 1505         {
 1506             Dsymbol sym = toParent().isAggregateDeclaration();
 1507             if (sym && !sym.isSpeculative())
 1508                 global.gag = 0;
 1509         }
 1510 
 1511         if (_scope)
 1512         {
 1513             inuse++;
 1514             _init = _init.initializerSemantic(_scope, type, INITinterpret);
 1515             _scope = null;
 1516             inuse--;
 1517         }
 1518 
 1519         Expression e = _init.initializerToExpression(needFullType ? type : null);
 1520         global.gag = oldgag;
 1521         return e;
 1522     }
 1523 
 1524     /*******************************************
 1525      * Helper function for the expansion of manifest constant.
 1526      */
 1527     extern (D) final Expression expandInitializer(Loc loc)
 1528     {
 1529         assert((storage_class & STC.manifest) && _init);
 1530 
 1531         auto e = getConstInitializer();
 1532         if (!e)
 1533         {
 1534             .error(loc, "cannot make expression out of initializer for `%s`", toChars());
 1535             return ErrorExp.get();
 1536         }
 1537 
 1538         e = e.copy();
 1539         e.loc = loc;    // for better error message
 1540         return e;
 1541     }
 1542 
 1543     override final void checkCtorConstInit()
 1544     {
 1545         version (none)
 1546         {
 1547             /* doesn't work if more than one static ctor */
 1548             if (ctorinit == 0 && isCtorinit() && !isField())
 1549                 error("missing initializer in static constructor for const variable");
 1550         }
 1551     }
 1552 
 1553     /************************************
 1554      * Check to see if this variable is actually in an enclosing function
 1555      * rather than the current one.
 1556      * Update nestedrefs[], closureVars[] and outerVars[].
 1557      * Returns: true if error occurs.
 1558      */
 1559     extern (D) final bool checkNestedReference(Scope* sc, Loc loc)
 1560     {
 1561         //printf("VarDeclaration::checkNestedReference() %s\n", toChars());
 1562         if (sc.intypeof == 1 || (sc.flags & SCOPE.ctfe))
 1563             return false;
 1564         if (!parent || parent == sc.parent)
 1565             return false;
 1566         if (isDataseg() || (storage_class & STC.manifest))
 1567             return false;
 1568 
 1569         // The current function
 1570         FuncDeclaration fdthis = sc.parent.isFuncDeclaration();
 1571         if (!fdthis)
 1572             return false; // out of function scope
 1573 
 1574         Dsymbol p = toParent2();
 1575 
 1576         // Function literals from fdthis to p must be delegates
 1577         ensureStaticLinkTo(fdthis, p);
 1578 
 1579         // The function that this variable is in
 1580         FuncDeclaration fdv = p.isFuncDeclaration();
 1581         if (!fdv || fdv == fdthis)
 1582             return false;
 1583 
 1584         // Add fdthis to nestedrefs[] if not already there
 1585         if (!nestedrefs.contains(fdthis))
 1586             nestedrefs.push(fdthis);
 1587 
 1588         //printf("\tfdv = %s\n", fdv.toChars());
 1589         //printf("\tfdthis = %s\n", fdthis.toChars());
 1590         if (loc.isValid())
 1591         {
 1592             if (fdthis.getLevelAndCheck(loc, sc, fdv, this) == fdthis.LevelError)
 1593                 return true;
 1594         }
 1595 
 1596         // Add this VarDeclaration to fdv.closureVars[] if not already there
 1597         if (!sc.intypeof && !(sc.flags & SCOPE.compile) &&
 1598             // https://issues.dlang.org/show_bug.cgi?id=17605
 1599             (fdv.flags & FUNCFLAG.compileTimeOnly || !(fdthis.flags & FUNCFLAG.compileTimeOnly))
 1600            )
 1601         {
 1602             if (!fdv.closureVars.contains(this))
 1603                 fdv.closureVars.push(this);
 1604         }
 1605 
 1606         if (!fdthis.outerVars.contains(this))
 1607             fdthis.outerVars.push(this);
 1608 
 1609         //printf("fdthis is %s\n", fdthis.toChars());
 1610         //printf("var %s in function %s is nested ref\n", toChars(), fdv.toChars());
 1611         // __dollar creates problems because it isn't a real variable
 1612         // https://issues.dlang.org/show_bug.cgi?id=3326
 1613         if (ident == Id.dollar)
 1614         {
 1615             .error(loc, "cannnot use `$` inside a function literal");
 1616             return true;
 1617         }
 1618         if (ident == Id.withSym) // https://issues.dlang.org/show_bug.cgi?id=1759
 1619         {
 1620             ExpInitializer ez = _init.isExpInitializer();
 1621             assert(ez);
 1622             Expression e = ez.exp;
 1623             if (e.op == TOK.construct || e.op == TOK.blit)
 1624                 e = (cast(AssignExp)e).e2;
 1625             return lambdaCheckForNestedRef(e, sc);
 1626         }
 1627 
 1628         return false;
 1629     }
 1630 
 1631     override final Dsymbol toAlias()
 1632     {
 1633         //printf("VarDeclaration::toAlias('%s', this = %p, aliassym = %p)\n", toChars(), this, aliassym);
 1634         if ((!type || !type.deco) && _scope)
 1635             dsymbolSemantic(this, _scope);
 1636 
 1637         assert(this != aliassym);
 1638         Dsymbol s = aliassym ? aliassym.toAlias() : this;
 1639         return s;
 1640     }
 1641 
 1642     // Eliminate need for dynamic_cast
 1643     override final inout(VarDeclaration) isVarDeclaration() inout
 1644     {
 1645         return this;
 1646     }
 1647 
 1648     override void accept(Visitor v)
 1649     {
 1650         v.visit(this);
 1651     }
 1652 
 1653     /**********************************
 1654      * Determine if `this` has a lifetime that lasts past
 1655      * the destruction of `v`
 1656      * Params:
 1657      *  v = variable to test against
 1658      * Returns:
 1659      *  true if it does
 1660      */
 1661     final bool enclosesLifetimeOf(VarDeclaration v) const pure
 1662     {
 1663         return sequenceNumber < v.sequenceNumber;
 1664     }
 1665 
 1666     /***************************************
 1667      * Add variable to maybes[].
 1668      * When a maybescope variable `v` is assigned to a maybescope variable `this`,
 1669      * we cannot determine if `this` is actually scope until the semantic
 1670      * analysis for the function is completed. Thus, we save the data
 1671      * until then.
 1672      * Params:
 1673      *  v = an STC.maybescope variable that was assigned to `this`
 1674      */
 1675     final void addMaybe(VarDeclaration v)
 1676     {
 1677         //printf("add %s to %s's list of dependencies\n", v.toChars(), toChars());
 1678         if (!maybes)
 1679             maybes = new VarDeclarations();
 1680         maybes.push(v);
 1681     }
 1682 }
 1683 
 1684 /***********************************************************
 1685  * This is a shell around a back end symbol
 1686  */
 1687 extern (C++) final class SymbolDeclaration : Declaration
 1688 {
 1689     StructDeclaration dsym;
 1690 
 1691     extern (D) this(const ref Loc loc, StructDeclaration dsym)
 1692     {
 1693         super(loc, dsym.ident);
 1694         this.dsym = dsym;
 1695         storage_class |= STC.const_;
 1696     }
 1697 
 1698     // Eliminate need for dynamic_cast
 1699     override inout(SymbolDeclaration) isSymbolDeclaration() inout
 1700     {
 1701         return this;
 1702     }
 1703 
 1704     override void accept(Visitor v)
 1705     {
 1706         v.visit(this);
 1707     }
 1708 }
 1709 
 1710 /***********************************************************
 1711  */
 1712 extern (C++) class TypeInfoDeclaration : VarDeclaration
 1713 {
 1714     Type tinfo;
 1715 
 1716     final extern (D) this(Type tinfo)
 1717     {
 1718         super(Loc.initial, Type.dtypeinfo.type, tinfo.getTypeInfoIdent(), null);
 1719         this.tinfo = tinfo;
 1720         storage_class = STC.static_ | STC.gshared;
 1721         protection = Prot(Prot.Kind.public_);
 1722         linkage = LINK.c;
 1723         alignment = target.ptrsize;
 1724     }
 1725 
 1726     static TypeInfoDeclaration create(Type tinfo)
 1727     {
 1728         return new TypeInfoDeclaration(tinfo);
 1729     }
 1730 
 1731     override final Dsymbol syntaxCopy(Dsymbol s)
 1732     {
 1733         assert(0); // should never be produced by syntax
 1734     }
 1735 
 1736     override final const(char)* toChars() const
 1737     {
 1738         //printf("TypeInfoDeclaration::toChars() tinfo = %s\n", tinfo.toChars());
 1739         OutBuffer buf;
 1740         buf.writestring("typeid(");
 1741         buf.writestring(tinfo.toChars());
 1742         buf.writeByte(')');
 1743         return buf.extractChars();
 1744     }
 1745 
 1746     override final inout(TypeInfoDeclaration) isTypeInfoDeclaration() inout
 1747     {
 1748         return this;
 1749     }
 1750 
 1751     override void accept(Visitor v)
 1752     {
 1753         v.visit(this);
 1754     }
 1755 }
 1756 
 1757 /***********************************************************
 1758  */
 1759 extern (C++) final class TypeInfoStructDeclaration : TypeInfoDeclaration
 1760 {
 1761     extern (D) this(Type tinfo)
 1762     {
 1763         super(tinfo);
 1764         if (!Type.typeinfostruct)
 1765         {
 1766             ObjectNotFound(Id.TypeInfo_Struct);
 1767         }
 1768         type = Type.typeinfostruct.type;
 1769     }
 1770 
 1771     static TypeInfoStructDeclaration create(Type tinfo)
 1772     {
 1773         return new TypeInfoStructDeclaration(tinfo);
 1774     }
 1775 
 1776     override void accept(Visitor v)
 1777     {
 1778         v.visit(this);
 1779     }
 1780 }
 1781 
 1782 /***********************************************************
 1783  */
 1784 extern (C++) final class TypeInfoClassDeclaration : TypeInfoDeclaration
 1785 {
 1786     extern (D) this(Type tinfo)
 1787     {
 1788         super(tinfo);
 1789         if (!Type.typeinfoclass)
 1790         {
 1791             ObjectNotFound(Id.TypeInfo_Class);
 1792         }
 1793         type = Type.typeinfoclass.type;
 1794     }
 1795 
 1796     static TypeInfoClassDeclaration create(Type tinfo)
 1797     {
 1798         return new TypeInfoClassDeclaration(tinfo);
 1799     }
 1800 
 1801     override void accept(Visitor v)
 1802     {
 1803         v.visit(this);
 1804     }
 1805 }
 1806 
 1807 /***********************************************************
 1808  */
 1809 extern (C++) final class TypeInfoInterfaceDeclaration : TypeInfoDeclaration
 1810 {
 1811     extern (D) this(Type tinfo)
 1812     {
 1813         super(tinfo);
 1814         if (!Type.typeinfointerface)
 1815         {
 1816             ObjectNotFound(Id.TypeInfo_Interface);
 1817         }
 1818         type = Type.typeinfointerface.type;
 1819     }
 1820 
 1821     static TypeInfoInterfaceDeclaration create(Type tinfo)
 1822     {
 1823         return new TypeInfoInterfaceDeclaration(tinfo);
 1824     }
 1825 
 1826     override void accept(Visitor v)
 1827     {
 1828         v.visit(this);
 1829     }
 1830 }
 1831 
 1832 /***********************************************************
 1833  */
 1834 extern (C++) final class TypeInfoPointerDeclaration : TypeInfoDeclaration
 1835 {
 1836     extern (D) this(Type tinfo)
 1837     {
 1838         super(tinfo);
 1839         if (!Type.typeinfopointer)
 1840         {
 1841             ObjectNotFound(Id.TypeInfo_Pointer);
 1842         }
 1843         type = Type.typeinfopointer.type;
 1844     }
 1845 
 1846     static TypeInfoPointerDeclaration create(Type tinfo)
 1847     {
 1848         return new TypeInfoPointerDeclaration(tinfo);
 1849     }
 1850 
 1851     override void accept(Visitor v)
 1852     {
 1853         v.visit(this);
 1854     }
 1855 }
 1856 
 1857 /***********************************************************
 1858  */
 1859 extern (C++) final class TypeInfoArrayDeclaration : TypeInfoDeclaration
 1860 {
 1861     extern (D) this(Type tinfo)
 1862     {
 1863         super(tinfo);
 1864         if (!Type.typeinfoarray)
 1865         {
 1866             ObjectNotFound(Id.TypeInfo_Array);
 1867         }
 1868         type = Type.typeinfoarray.type;
 1869     }
 1870 
 1871     static TypeInfoArrayDeclaration create(Type tinfo)
 1872     {
 1873         return new TypeInfoArrayDeclaration(tinfo);
 1874     }
 1875 
 1876     override void accept(Visitor v)
 1877     {
 1878         v.visit(this);
 1879     }
 1880 }
 1881 
 1882 /***********************************************************
 1883  */
 1884 extern (C++) final class TypeInfoStaticArrayDeclaration : TypeInfoDeclaration
 1885 {
 1886     extern (D) this(Type tinfo)
 1887     {
 1888         super(tinfo);
 1889         if (!Type.typeinfostaticarray)
 1890         {
 1891             ObjectNotFound(Id.TypeInfo_StaticArray);
 1892         }
 1893         type = Type.typeinfostaticarray.type;
 1894     }
 1895 
 1896     static TypeInfoStaticArrayDeclaration create(Type tinfo)
 1897     {
 1898         return new TypeInfoStaticArrayDeclaration(tinfo);
 1899     }
 1900 
 1901     override void accept(Visitor v)
 1902     {
 1903         v.visit(this);
 1904     }
 1905 }
 1906 
 1907 /***********************************************************
 1908  */
 1909 extern (C++) final class TypeInfoAssociativeArrayDeclaration : TypeInfoDeclaration
 1910 {
 1911     extern (D) this(Type tinfo)
 1912     {
 1913         super(tinfo);
 1914         if (!Type.typeinfoassociativearray)
 1915         {
 1916             ObjectNotFound(Id.TypeInfo_AssociativeArray);
 1917         }
 1918         type = Type.typeinfoassociativearray.type;
 1919     }
 1920 
 1921     static TypeInfoAssociativeArrayDeclaration create(Type tinfo)
 1922     {
 1923         return new TypeInfoAssociativeArrayDeclaration(tinfo);
 1924     }
 1925 
 1926     override void accept(Visitor v)
 1927     {
 1928         v.visit(this);
 1929     }
 1930 }
 1931 
 1932 /***********************************************************
 1933  */
 1934 extern (C++) final class TypeInfoEnumDeclaration : TypeInfoDeclaration
 1935 {
 1936     extern (D) this(Type tinfo)
 1937     {
 1938         super(tinfo);
 1939         if (!Type.typeinfoenum)
 1940         {
 1941             ObjectNotFound(Id.TypeInfo_Enum);
 1942         }
 1943         type = Type.typeinfoenum.type;
 1944     }
 1945 
 1946     static TypeInfoEnumDeclaration create(Type tinfo)
 1947     {
 1948         return new TypeInfoEnumDeclaration(tinfo);
 1949     }
 1950 
 1951     override void accept(Visitor v)
 1952     {
 1953         v.visit(this);
 1954     }
 1955 }
 1956 
 1957 /***********************************************************
 1958  */
 1959 extern (C++) final class TypeInfoFunctionDeclaration : TypeInfoDeclaration
 1960 {
 1961     extern (D) this(Type tinfo)
 1962     {
 1963         super(tinfo);
 1964         if (!Type.typeinfofunction)
 1965         {
 1966             ObjectNotFound(Id.TypeInfo_Function);
 1967         }
 1968         type = Type.typeinfofunction.type;
 1969     }
 1970 
 1971     static TypeInfoFunctionDeclaration create(Type tinfo)
 1972     {
 1973         return new TypeInfoFunctionDeclaration(tinfo);
 1974     }
 1975 
 1976     override void accept(Visitor v)
 1977     {
 1978         v.visit(this);
 1979     }
 1980 }
 1981 
 1982 /***********************************************************
 1983  */
 1984 extern (C++) final class TypeInfoDelegateDeclaration : TypeInfoDeclaration
 1985 {
 1986     extern (D) this(Type tinfo)
 1987     {
 1988         super(tinfo);
 1989         if (!Type.typeinfodelegate)
 1990         {
 1991             ObjectNotFound(Id.TypeInfo_Delegate);
 1992         }
 1993         type = Type.typeinfodelegate.type;
 1994     }
 1995 
 1996     static TypeInfoDelegateDeclaration create(Type tinfo)
 1997     {
 1998         return new TypeInfoDelegateDeclaration(tinfo);
 1999     }
 2000 
 2001     override void accept(Visitor v)
 2002     {
 2003         v.visit(this);
 2004     }
 2005 }
 2006 
 2007 /***********************************************************
 2008  */
 2009 extern (C++) final class TypeInfoTupleDeclaration : TypeInfoDeclaration
 2010 {
 2011     extern (D) this(Type tinfo)
 2012     {
 2013         super(tinfo);
 2014         if (!Type.typeinfotypelist)
 2015         {
 2016             ObjectNotFound(Id.TypeInfo_Tuple);
 2017         }
 2018         type = Type.typeinfotypelist.type;
 2019     }
 2020 
 2021     static TypeInfoTupleDeclaration create(Type tinfo)
 2022     {
 2023         return new TypeInfoTupleDeclaration(tinfo);
 2024     }
 2025 
 2026     override void accept(Visitor v)
 2027     {
 2028         v.visit(this);
 2029     }
 2030 }
 2031 
 2032 /***********************************************************
 2033  */
 2034 extern (C++) final class TypeInfoConstDeclaration : TypeInfoDeclaration
 2035 {
 2036     extern (D) this(Type tinfo)
 2037     {
 2038         super(tinfo);
 2039         if (!Type.typeinfoconst)
 2040         {
 2041             ObjectNotFound(Id.TypeInfo_Const);
 2042         }
 2043         type = Type.typeinfoconst.type;
 2044     }
 2045 
 2046     static TypeInfoConstDeclaration create(Type tinfo)
 2047     {
 2048         return new TypeInfoConstDeclaration(tinfo);
 2049     }
 2050 
 2051     override void accept(Visitor v)
 2052     {
 2053         v.visit(this);
 2054     }
 2055 }
 2056 
 2057 /***********************************************************
 2058  */
 2059 extern (C++) final class TypeInfoInvariantDeclaration : TypeInfoDeclaration
 2060 {
 2061     extern (D) this(Type tinfo)
 2062     {
 2063         super(tinfo);
 2064         if (!Type.typeinfoinvariant)
 2065         {
 2066             ObjectNotFound(Id.TypeInfo_Invariant);
 2067         }
 2068         type = Type.typeinfoinvariant.type;
 2069     }
 2070 
 2071     static TypeInfoInvariantDeclaration create(Type tinfo)
 2072     {
 2073         return new TypeInfoInvariantDeclaration(tinfo);
 2074     }
 2075 
 2076     override void accept(Visitor v)
 2077     {
 2078         v.visit(this);
 2079     }
 2080 }
 2081 
 2082 /***********************************************************
 2083  */
 2084 extern (C++) final class TypeInfoSharedDeclaration : TypeInfoDeclaration
 2085 {
 2086     extern (D) this(Type tinfo)
 2087     {
 2088         super(tinfo);
 2089         if (!Type.typeinfoshared)
 2090         {
 2091             ObjectNotFound(Id.TypeInfo_Shared);
 2092         }
 2093         type = Type.typeinfoshared.type;
 2094     }
 2095 
 2096     static TypeInfoSharedDeclaration create(Type tinfo)
 2097     {
 2098         return new TypeInfoSharedDeclaration(tinfo);
 2099     }
 2100 
 2101     override void accept(Visitor v)
 2102     {
 2103         v.visit(this);
 2104     }
 2105 }
 2106 
 2107 /***********************************************************
 2108  */
 2109 extern (C++) final class TypeInfoWildDeclaration : TypeInfoDeclaration
 2110 {
 2111     extern (D) this(Type tinfo)
 2112     {
 2113         super(tinfo);
 2114         if (!Type.typeinfowild)
 2115         {
 2116             ObjectNotFound(Id.TypeInfo_Wild);
 2117         }
 2118         type = Type.typeinfowild.type;
 2119     }
 2120 
 2121     static TypeInfoWildDeclaration create(Type tinfo)
 2122     {
 2123         return new TypeInfoWildDeclaration(tinfo);
 2124     }
 2125 
 2126     override void accept(Visitor v)
 2127     {
 2128         v.visit(this);
 2129     }
 2130 }
 2131 
 2132 /***********************************************************
 2133  */
 2134 extern (C++) final class TypeInfoVectorDeclaration : TypeInfoDeclaration
 2135 {
 2136     extern (D) this(Type tinfo)
 2137     {
 2138         super(tinfo);
 2139         if (!Type.typeinfovector)
 2140         {
 2141             ObjectNotFound(Id.TypeInfo_Vector);
 2142         }
 2143         type = Type.typeinfovector.type;
 2144     }
 2145 
 2146     static TypeInfoVectorDeclaration create(Type tinfo)
 2147     {
 2148         return new TypeInfoVectorDeclaration(tinfo);
 2149     }
 2150 
 2151     override void accept(Visitor v)
 2152     {
 2153         v.visit(this);
 2154     }
 2155 }
 2156 
 2157 /***********************************************************
 2158  * For the "this" parameter to member functions
 2159  */
 2160 extern (C++) final class ThisDeclaration : VarDeclaration
 2161 {
 2162     extern (D) this(const ref Loc loc, Type t)
 2163     {
 2164         super(loc, t, Id.This, null);
 2165         storage_class |= STC.nodtor;
 2166     }
 2167 
 2168     override Dsymbol syntaxCopy(Dsymbol s)
 2169     {
 2170         assert(0); // should never be produced by syntax
 2171     }
 2172 
 2173     override inout(ThisDeclaration) isThisDeclaration() inout
 2174     {
 2175         return this;
 2176     }
 2177 
 2178     override void accept(Visitor v)
 2179     {
 2180         v.visit(this);
 2181     }
 2182 }