# dmd.dsymbol

The base class for a D symbol, which can be a module, variable, function, enum, etc.

#### Authors

Walter Bright

#### License

Boost License 1.0

Source: dsymbol.d

Documentation: https://dlang.org/phobos/dmd_dsymbol.html

Coverage: https://codecov.io/gh/dlang/dmd/src/master/src/dmd/dsymbol.d

- `foreachDsymbol`

  #### Declaration

  `int `foreachDsymbol`(Dsymbols* `symbols`, scope int delegate(Dsymbol) `dg`);`

  Calls `dg`(Dsymbol *sym) for each Dsymbol. If `dg` returns !=0, stops and returns that value else returns 0.

  #### Parameters

  `Dsymbols* `symbols`` | Dsymbols
  `int delegate(Dsymbol) `dg`` | delegate to call for each Dsymbol

  #### Return Value

  last value returned by `dg`()

  #### See Also

- `foreachDsymbol`

  #### Declaration

  `void `foreachDsymbol`(Dsymbols* `symbols`, scope void delegate(Dsymbol) `dg`);`

  Calls `dg`(Dsymbol *sym) for each Dsymbol.

  #### Parameters

  `Dsymbols* `symbols`` | Dsymbols
  `void delegate(Dsymbol) `dg`` | delegate to call for each Dsymbol

  #### See Also

- `FieldState`

  #### Declaration

  `struct `FieldState`;`

  Struct/Class/Union field state. Used for transitory information when setting field offsets, such as bit fields.

  - `offset`

    #### Declaration

    `uint `offset`;`

    byte `offset` for next field

  - `fieldOffset`

    #### Declaration

    `uint `fieldOffset`;`

    byte offset for the start of the bit field

  - `fieldSize`

    #### Declaration

    `uint `fieldSize`;`

    byte size of field

  - `fieldAlign`

    #### Declaration

    `uint `fieldAlign`;`

    byte alignment of field

  - `bitOffset`

    #### Declaration

    `uint `bitOffset`;`

    bit offset for field

  - `inFlight`

    #### Declaration

    `bool `inFlight`;`

    bit field is in flight

- `Dsymbol`

  #### Declaration

  `class `Dsymbol`: dmd.ast_node.ASTNode;`

  - `cppnamespace`

    #### Declaration

    `CPPNamespaceDeclaration `cppnamespace`;`

    C++ namespace this symbol belongs to

  - `localNum`

    #### Declaration

    `ushort `localNum`;`

    perturb mangled name to avoid collisions with those in FuncDeclaration.localsymtab

  - `getModule`

    #### Declaration

    `final Module `getModule`();`

    Determine which Module a Dsymbol is in.

  - `getAccessModule`

    #### Declaration

    `final Module `getAccessModule`();`

    Determine which Module a Dsymbol is in, as far as access rights go.

  - `pastMixin`

    #### Declaration

    `final inout inout(Dsymbol) `pastMixin`();`

    ``pastMixin`` returns the enclosing symbol if this is a template mixin.

    #### Discussion

    `pastMixinAndNspace` does likewise, additionally skipping over Nspaces that are mangleOnly.
    See also `parent`, `toParent` and `toParent2`.

  - `toParent`

    #### Declaration

    `final inout inout(Dsymbol) `toParent`();
    final inout inout(Dsymbol) `toParent2`();
    final inout inout(Dsymbol) `toParentDecl`();
    final inout inout(Dsymbol) `toParentLocal`();`

    `parent` field returns a lexically enclosing scope symbol this is a member of.

    #### Discussion

    ``toParent`()` returns a logically enclosing scope symbol this is a member of. It skips over TemplateMixin's.
    ``toParent2`()` returns an enclosing scope symbol this is living at runtime. It skips over both TemplateInstance's and TemplateMixin's. It's used when looking for the 'this' pointer of the enclosing function/class.
    ``toParentDecl`()` similar to ``toParent2`()` but always follows the template declaration scope instead of the instantiation scope.
    ``toParentLocal`()` similar to ``toParentDecl`()` but follows the instantiation scope if a template declaration is non-local i.e. global or static.

    #### Examples

    1. `module mod; template Foo(alias a) { mixin Bar!(); } mixin template Bar() { public { // VisibilityDeclaration void baz() { a = 2; } } } void test() { int v = 1; alias foo = Foo!(v); foo.baz(); assert(v == 2); } // s == FuncDeclaration('mod.test.Foo!().Bar!().baz()') // s.parent == TemplateMixin('mod.test.Foo!().Bar!()') // s.toParent() == TemplateInstance('mod.test.Foo!()') // s.toParent2() == FuncDeclaration('mod.test') // s.toParentDecl() == Module('mod') // s.toParentLocal() == FuncDeclaration('mod.test')`
  - `toParentP`

    #### Declaration

    `final Dsymbol `toParentP`(Dsymbol `p1`, Dsymbol `p2` = null);`

    Returns the declaration scope scope of `this` unless any of the symbols ``p1`` or ``p2`` resides in its enclosing instantiation scope then the latter is returned.

  - `followInstantiationContext`

    #### Declaration

    `final bool `followInstantiationContext`(Dsymbol `p1`, Dsymbol `p2` = null);`

    Returns `true` if any of the symbols ``p1`` or ``p2`` resides in the enclosing instantiation scope of `this`.

  - `arraySyntaxCopy`

    #### Declaration

    `static Dsymbols* `arraySyntaxCopy`(Dsymbols* `a`);`

    Do syntax copy of an array of Dsymbol's.

  - `toAlias`

    #### Declaration

    `Dsymbol `toAlias`();`

    If this symbol is really an alias for another, return that other. If needed, semantic() is invoked due to resolve forward reference.

  - `toAlias2`

    #### Declaration

    `Dsymbol `toAlias2`();`

    Resolve recursive tuple expansion in eponymous template.

  - `setScope`

    #### Declaration

    `void `setScope`(Scope* `sc`);`

    Set scope for future semantic analysis so we can deal better with forward references.

  - `search`

    #### Declaration

    `Dsymbol `search`(const ref Loc `loc`, Identifier `ident`, int `flags` = IgnoreNone);`

    Search for `ident` as member of s.

    #### Parameters

    `Loc `loc`` | location to print for error messages
    `Identifier `ident`` | identifier to `search` for
    `int `flags`` | IgnoreXXXX

    #### Return Value

    `null` if not found

  - `searchX`

    #### Declaration

    `final Dsymbol `searchX`(const ref Loc `loc`, Scope* `sc`, RootObject `id`, int `flags`);`

    Search for identifier `id` as a member of `this`. ``id`` may be a template instance.

    #### Parameters

    `Loc `loc`` | location to print the error messages
    `Scope* `sc`` | the scope where the symbol is located
    `RootObject `id`` | the `id` of the symbol
    `int `flags`` | the search `flags` which can be `SearchLocalsOnly` or `IgnorePrivateImports`

    #### Return Value

    symbol found, NULL if not

  - `size`

    #### Declaration

    `d_uns64 `size`(const ref Loc `loc`);`

    #### Return Value

    SIZE_INVALID when the `size` cannot be determined

  - `isMember`

    #### Declaration

    `final inout inout(AggregateDeclaration) `isMember`();`

    Returns an AggregateDeclaration when toParent() is that.

  - `isMember2`

    #### Declaration

    `final inout inout(AggregateDeclaration) `isMember2`();`

    Returns an AggregateDeclaration when toParent2() is that.

  - `isMemberDecl`

    #### Declaration

    `final inout inout(AggregateDeclaration) `isMemberDecl`();`

    Returns an AggregateDeclaration when toParentDecl() is that.

  - `isMemberLocal`

    #### Declaration

    `final inout inout(AggregateDeclaration) `isMemberLocal`();`

    Returns an AggregateDeclaration when toParentLocal() is that.

  - `visible`

    #### Declaration

    `pure nothrow @nogc @safe Visibility `visible`();`

  - `syntaxCopy`

    #### Declaration

    `Dsymbol `syntaxCopy`(Dsymbol `s`);`

    Copy the syntax. Used for template instantiations. If `s` is NULL, allocate the new object, otherwise fill it in.

  - `oneMember`

    #### Declaration

    `bool `oneMember`(Dsymbol* `ps`, Identifier `ident`);`

    Determine if this symbol is only one.

    #### Return Value

    `false`, *`ps` = NULL: There are 2 or more symbols `true`, *`ps` = NULL: There are zero symbols `true`, *`ps` = symbol: The one and only one symbol

  - `oneMembers`

    #### Declaration

    `static bool `oneMembers`(Dsymbols* `members`, Dsymbol* `ps`, Identifier `ident`);`

    Same as Dsymbol::oneMember(), but look at an array of Dsymbols.

  - `hasPointers`

    #### Declaration

    `bool `hasPointers`();`

    Is Dsymbol a variable that contains pointers?

  - `addComment`

    #### Declaration

    `void `addComment`(const(char)* `comment`);`

    Add documentation `comment` to Dsymbol. Ignore NULL comments.

  - `inNonRoot`

    #### Declaration

    `final bool `inNonRoot`();`

    Returns `true` if this symbol is defined in a non-root module without instantiation.

  - `accept`

    #### Declaration

    `void `accept`(Visitor `v`);`

- `ScopeDsymbol`

  #### Declaration

  `class `ScopeDsymbol`: dmd.dsymbol.Dsymbol;`

  Dsymbol that generates a scope

  - `search`

    #### Declaration

    `Dsymbol `search`(const ref Loc `loc`, Identifier `ident`, int `flags` = SearchLocalsOnly);`

    This function is #1 on the list of functions that eat cpu time. Be very, very careful about slowing it down.

  - `findGetMembers`

    #### Declaration

    `final FuncDeclaration `findGetMembers`();`

    Look for member of the form: const(MemberInfo)[] getMembers(string); Returns NULL if not found

  - `symtabInsert`

    #### Declaration

    `Dsymbol `symtabInsert`(Dsymbol `s`);`

    Insert Dsymbol in table.

    #### Parameters

    `Dsymbol `s`` | symbol to add

    #### Return Value

    `null` if already in table, ``s`` if inserted

  - `symtabLookup`

    #### Declaration

    `Dsymbol `symtabLookup`(Dsymbol `s`, Identifier `id`);`

    Look up identifier in symbol table.

    #### Parameters

    `Dsymbol `s`` | symbol
    `Identifier `id`` | identifier to look up

    #### Return Value

    Dsymbol if found, `null` if not

  - `hasStaticCtorOrDtor`

    #### Declaration

    `bool `hasStaticCtorOrDtor`();`

    Return `true` if any of the members are static ctors or static dtors, or if any members have members that are.

  - `_foreach`

    #### Declaration

    `static int `_foreach`(Scope* `sc`, Dsymbols* `members`, scope ForeachDg `dg`, size_t* `pn` = null);`

    Expands attribute declarations in `members` in depth first order. Calls `dg`(size_t symidx, Dsymbol *sym) for each member. If `dg` returns !=0, stops and returns that value else returns 0. Use this function to avoid the O(N + N^2/2) complexity of calculating dim and calling N times getNth.

    #### Return Value

    last value returned by `dg`()

- `WithScopeSymbol`

  #### Declaration

  `class `WithScopeSymbol`: dmd.dsymbol.ScopeDsymbol;`

  With statement scope

- `ArrayScopeSymbol`

  #### Declaration

  `class `ArrayScopeSymbol`: dmd.dsymbol.ScopeDsymbol;`

  Array Index/Slice scope

  - `search`

    #### Declaration

    `Dsymbol `search`(const ref Loc `loc`, Identifier `ident`, int `flags` = IgnoreNone);`

    This override is used to solve `$`

- `OverloadSet`

  #### Declaration

  `class `OverloadSet`: dmd.dsymbol.Dsymbol;`

  Overload Sets

- `ForwardingScopeDsymbol`

  #### Declaration

  `class `ForwardingScopeDsymbol`: dmd.dsymbol.ScopeDsymbol;`

  Forwarding ScopeDsymbol. Used by ForwardingAttribDeclaration and ForwardingScopeDeclaration to forward symbol insertions to another scope. See `dmd.attrib.ForwardingAttribDeclaration` for more details.

  - `forward`

    #### Declaration

    `ScopeDsymbol `forward`;`

    Symbol to `forward` insertions to. Can be `null` before being lazily initialized.

  - `symtabLookup`

    #### Declaration

    `Dsymbol `symtabLookup`(Dsymbol `s`, Identifier `id`);`

    This override handles the following two cases: static foreach (i, i; [0]) { ... } and static foreach (i; [0]) { enum i = 2; }

- `ExpressionDsymbol`

  #### Declaration

  `class `ExpressionDsymbol`: dmd.dsymbol.Dsymbol;`

  Class that holds an expression in a Dsymbol wrapper. This is not an AST node, but a class used to pass an expression as a function parameter of type Dsymbol.

- `AliasAssign`

  #### Declaration

  `class `AliasAssign`: dmd.dsymbol.Dsymbol;`

  Encapsulate assigning to an alias: `identifier = type;` `identifier = symbol;` where `identifier` is an AliasDeclaration in scope.

  - `ident`

    #### Declaration

    `Identifier `ident`;`

    Dsymbol's `ident` will be `null`, as this class is anonymous

  - `type`

    #### Declaration

    `Type `type`;`

    replace previous RHS of AliasDeclaration with ``type``

  - `aliassym`

    #### Declaration

    `Dsymbol `aliassym`;`

    replace previous RHS of AliasDeclaration with ``aliassym``

  - `this`

    #### Declaration

    `this(const ref Loc `loc`, Identifier `ident`, Type `type`, Dsymbol `aliassym`);`

    only one of `type` and `aliassym` can be != `null`

- `DsymbolTable`

  #### Declaration

  `class `DsymbolTable`: dmd.root.rootobject.RootObject;`

  Table of Dsymbol's

  - `lookup`

    #### Declaration

    `Dsymbol `lookup`(const Identifier `ident`);`

    Look up Identifier in symbol table

    #### Parameters

    `Identifier `ident`` | identifer to look up

    #### Return Value

    Dsymbol if found, `null` if not

  - `update`

    #### Declaration

    `void `update`(Dsymbol `s`);`

    Replace existing symbol in symbol table with ``s``. If it'`s` not there, add it.

    #### Parameters

    `Dsymbol `s`` | replacement symbol with same identifier

  - `insert`

    #### Declaration

    `Dsymbol `insert`(Dsymbol `s`);`

    Insert Dsymbol in table.

    #### Parameters

    `Dsymbol `s`` | symbol to add

    #### Return Value

    `null` if already in table, ``s`` if inserted

  - `insert`

    #### Declaration

    `Dsymbol `insert`(const Identifier `ident`, Dsymbol `s`);`

    Insert Dsymbol in table.

    #### Parameters

    `Identifier `ident`` | identifier to serve as index
    `Dsymbol `s`` | symbol to add

    #### Return Value

    `null` if already in table, ``s`` if inserted

  - `length`

    #### Declaration

    `const pure size_t `length`();`

    #### Return Value

    number of symbols in symbol table

- `handleTagSymbols`

  #### Declaration

  `Dsymbol `handleTagSymbols`(ref Scope `sc`, Dsymbol `s`, Dsymbol `s2`, ScopeDsymbol `sds`);`

  ImportC tag symbols sit in a parallel symbol table, so that this C code works:

  1. `struct S { a; }; int S; struct S s;`
  But there are relatively few such tag symbols, so that would be a waste of memory and complexity. An additional problem is we'd like the D side to find the tag symbols with ordinary lookup, not lookup in both tables, if the tag symbol is not conflicting with an ordinary symbol. The solution is to put the tag symbols that conflict into an associative array, indexed by the address of the ordinary symbol that conflicts with it. C has no modules, so this associative array is tagSymTab[] in ModuleDeclaration. A side effect of our approach is that D code cannot access a tag symbol that is hidden by an ordinary symbol. This is more of a theoretical problem, as nobody has mentioned it when importing C headers. If someone wants to do it, too bad so sad. Change the C code. This function fixes up the symbol table when faced with adding a new symbol ``s`` when there is an existing symbol ``s2`` with the same name. C also allows forward and prototype declarations of tag symbols, this function merges those.

  #### Parameters

  `Scope `sc`` | context
  `Dsymbol `s`` | symbol to add to symbol table
  `Dsymbol `s2`` | existing declaration
  `ScopeDsymbol `sds`` | symbol table

  #### Return Value

  if `s` and `s2` are successfully put in symbol table then return the merged symbol, `null` if they conflict

- `handleSymbolRedeclarations`

  #### Declaration

  `Dsymbol `handleSymbolRedeclarations`(ref Scope `sc`, Dsymbol `s`, Dsymbol `s2`, ScopeDsymbol `sds`);`

  ImportC allows redeclarations of C variables, functions and typedefs. extern int x; int x = 3; and: extern void f(); void f() { } Attempt to merge them.

  #### Parameters

  `Scope `sc`` | context
  `Dsymbol `s`` | symbol to add to symbol table
  `Dsymbol `s2`` | existing declaration
  `ScopeDsymbol `sds`` | symbol table

  #### Return Value

  if `s` and `s2` are successfully put in symbol table then return the merged symbol, `null` if they conflict