# dmd.attrib

Defines declarations of various attributes.

#### Discussion

The term 'attribute' refers to things that can apply to a larger scope than a single declaration. Among them are:

- Alignment (`align(8)`)
- User defined attributes (`@UDA`)
- Function Attributes (`@safe`)
- Storage classes (`static`, `__gshared`)
- Mixin declarations (`mixin("int x;")`)
- Conditional compilation (`static if`, `static foreach`)
- Linkage (`extern(C)`)
- Anonymous structs / unions
- Protection (`private`, `public`)
- Deprecated declarations (`@deprecated`)

#### Authors

Walter Bright

#### License

Boost License 1.0

Source: attrib.d

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

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

- `AttribDeclaration`

  #### Declaration

  `abstract class `AttribDeclaration`: dmd.dsymbol.Dsymbol;`

  Abstract attribute applied to Dsymbol's used as a common ancestor for storage classes (StorageClassDeclaration), linkage (LinkageDeclaration) and others.

  - `decl`

    #### Declaration

    `Dsymbols* `decl`;`

    Dsymbol's affected by this AttribDeclaration

  - `createNewScope`

    #### Declaration

    `static Scope* `createNewScope`(Scope* `sc`, StorageClass `stc`, LINK `linkage`, CPPMANGLE `cppmangle`, Visibility `visibility`, int `explicitVisibility`, AlignDeclaration `aligndecl`, PragmaDeclaration `inlining`);`

    Create a new scope if one or more given attributes are different from the `sc`'s. If the returned scope != `sc`, the caller should pop the scope after it used.

  - `newScope`

    #### Declaration

    `Scope* `newScope`(Scope* `sc`);`

    A hook point to supply scope for members. addMember, setScope, importAll, semantic, semantic2 and semantic3 will use this.

  - `addObjcSymbols`

    #### Declaration

    `final void `addObjcSymbols`(ClassDeclarations* `classes`, ClassDeclarations* `categories`);`

- `StorageClassDeclaration`

  #### Declaration

  `class `StorageClassDeclaration`: dmd.attrib.AttribDeclaration;`

  Storage classes applied to Dsymbols, e.g. `const int i;`

  #### Discussion

- `DeprecatedDeclaration`

  #### Declaration

  `class `DeprecatedDeclaration`: dmd.attrib.StorageClassDeclaration;`

  Deprecation with an additional message applied to Dsymbols, e.g. `deprecated("Superseeded by foo") int bar;`. (Note that `deprecated int bar;` is currently represented as a StorageClassDeclaration with STC.deprecated_)

  #### Discussion

  `deprecated(<msg>) <decl...>`

  - `msg`

    #### Declaration

    `Expression `msg`;`

    deprecation message

  - `msgstr`

    #### Declaration

    `const(char)* `msgstr`;`

    cached string representation of msg

  - `newScope`

    #### Declaration

    `Scope* `newScope`(Scope* `sc`);`

    Provides a new scope with `STC.deprecated_` and `Scope.depdecl` set

    #### Discussion

    Calls `StorageClassDeclaration.`newScope`` (as it must be called or copied in any function overriding ``newScope``), then set the `Scope`'s depdecl.

    #### Return Value

    Always a new scope, to use for this `DeprecatedDeclaration`'s members.

- `LinkDeclaration`

  #### Declaration

  `class `LinkDeclaration`: dmd.attrib.AttribDeclaration;`

  Linkage attribute applied to Dsymbols, e.g. `extern(C) void foo()`.

  #### Discussion

  `extern(<linkage>) <decl...>`

  - `linkage`

    #### Declaration

    `LINK `linkage`;`

    either explicitly set or `default_`

- `CPPMangleDeclaration`

  #### Declaration

  `class `CPPMangleDeclaration`: dmd.attrib.AttribDeclaration;`

  Attribute declaring whether an external aggregate should be mangled as a struct or class in C++, e.g. `extern(C++, struct) class C { ... }`. This is required for correct name mangling on MSVC targets, see cppmanglewin.d for details.

  #### Discussion

  `extern(C++, <cppmangle>) <decl...>`

- `CPPNamespaceDeclaration`

  #### Declaration

  `class `CPPNamespaceDeclaration`: dmd.attrib.AttribDeclaration;`

  A node to represent an `extern(C++)` namespace attribute

  #### Discussion

  There are two ways to declarate a symbol as member of a namespace: `Nspace` and ``CPPNamespaceDeclaration``. The former creates a scope for the symbol, and inject them in the parent scope at the same time. The later, this class, has no semantic implications and is only used for mangling. Additionally, this class allows one to use reserved identifiers (D keywords) in the namespace.
  A ``CPPNamespaceDeclaration`` can be created from an `Identifier` (already resolved) or from an `Expression`, which is CTFE-ed and can be either a `TupleExp`, in which can additional ``CPPNamespaceDeclaration`` nodes are created, or a `StringExp`.
  Note that this class, like `Nspace`, matches only one identifier part of a namespace. For the namespace `"foo::bar"`, the will be a ``CPPNamespaceDeclaration`` with its `ident` set to `"bar"`, and its `namespace` field pointing to another ``CPPNamespaceDeclaration`` with its `ident` set to `"foo"`.

  - `exp`

    #### Declaration

    `Expression `exp`;`

    CTFE-able expression, resolving to `TupleExp` or `StringExp`

  - `newScope`

    #### Declaration

    `Scope* `newScope`(Scope* `sc`);`

    #### Return Value

    A copy of the parent scope, with `this` as `namespace` and C++ linkage

- `VisibilityDeclaration`

  #### Declaration

  `class `VisibilityDeclaration`: dmd.attrib.AttribDeclaration;`

  Visibility declaration for Dsymbols, e.g. `public int i;`

  #### Discussion

  `<visibility> <decl...>` or `package(<pkg_identifiers>) <decl...>` if `pkg_identifiers !is null`

  - `visibility`

    #### Declaration

    `Visibility `visibility`;`

    the `visibility`

  - `pkg_identifiers`

    #### Declaration

    `Identifier[] `pkg_identifiers`;`

    identifiers for `package(foo.bar)` or `null`

  - `this`

    #### Declaration

    `this(const ref Loc `loc`, Visibility `visibility`, Dsymbols* `decl`);`

    #### Parameters

    `Loc `loc`` | source location of attribute token
    `Visibility `visibility`` | `visibility` attribute data
    `Dsymbols* `decl`` | declarations which are affected by this `visibility` attribute

  - `this`

    #### Declaration

    `this(const ref Loc `loc`, Identifier[] `pkg_identifiers`, Dsymbols* `decl`);`

    #### Parameters

    `Loc `loc`` | source location of attribute token
    `Identifier[] `pkg_identifiers`` | list of identifiers for a qualified package name
    `Dsymbols* `decl`` | declarations which are affected by this visibility attribute

- `AlignDeclaration`

  #### Declaration

  `class `AlignDeclaration`: dmd.attrib.AttribDeclaration;`

  Alignment attribute for aggregates, members and variables.

  #### Discussion

  `align(<ealign>) <decl...>` or `align <decl...>` if `ealign` is `null`

  - `exps`

    #### Declaration

    `Expressions* `exps`;`

    Expression(s) yielding the desired alignment,

  - `salign`

    #### Declaration

    `structalign_t `salign`;`

    the largest value wins the actual alignment is Unknown until it's either set to the value of `ealign` or the default if `ealign` is `null` ( / an error ocurred)

- `AnonDeclaration`

  #### Declaration

  `class `AnonDeclaration`: dmd.attrib.AttribDeclaration;`

  An anonymous struct/union (defined by `isunion`).

  - `isunion`

    #### Declaration

    `bool `isunion`;`

    whether it's a union

  - `sem`

    #### Declaration

    `int `sem`;`

    1 if successful semantic()

  - `anonoffset`

    #### Declaration

    `uint `anonoffset`;`

    offset of anonymous struct

  - `anonstructsize`

    #### Declaration

    `uint `anonstructsize`;`

    size of anonymous struct

  - `anonalignsize`

    #### Declaration

    `uint `anonalignsize`;`

    size of anonymous struct for alignment purposes

- `PragmaDeclaration`

  #### Declaration

  `class `PragmaDeclaration`: dmd.attrib.AttribDeclaration;`

  Pragma applied to Dsymbols, e.g. `pragma(inline, true) void foo`, but not PragmaStatement's like `pragma(msg, "hello");`.

  #### Discussion

  pragma(, )

  - `args`

    #### Declaration

    `Expressions* `args`;`

    parameters of this pragma

- `ConditionalDeclaration`

  #### Declaration

  `class `ConditionalDeclaration`: dmd.attrib.AttribDeclaration;`

  A conditional compilation declaration, used for `version` / `debug` and specialized for `static if`.

  #### Discussion

  { } else { }

  - `condition`

    #### Declaration

    `Condition `condition`;`

    `condition` deciding whether decl or elsedecl applies

  - `elsedecl`

    #### Declaration

    `Dsymbols* `elsedecl`;`

    array of Dsymbol's for else block

- `StaticIfDeclaration`

  #### Declaration

  `class `StaticIfDeclaration`: dmd.attrib.ConditionalDeclaration;`

  ` { static if () { } else { } }`

  - `scopesym`

    #### Declaration

    `ScopeDsymbol `scopesym`;`

    enclosing symbol (e.g. module) where symbols will be inserted

  - `include`

    #### Declaration

    `Dsymbols* `include`(Scope* `sc`);`

    Different from other AttribDeclaration subclasses, `include`() call requires the completion of addMember and setScope phases.

- `StaticForeachDeclaration`

  #### Declaration

  `class `StaticForeachDeclaration`: dmd.attrib.AttribDeclaration;`

  Static foreach at declaration scope, like: static foreach (i; [0, 1, 2]){ }

  - `sfe`

    #### Declaration

    `StaticForeach `sfe`;`

    contains `static foreach` expansion logic

  - `scopesym`

    #### Declaration

    `ScopeDsymbol `scopesym`;`

    cached enclosing scope (mimics `static if` declaration)

  - `onStack`

    #### Declaration

    `bool `onStack`;`

    `include` can be called multiple times, but a `static foreach` should be expanded at most once. Achieved by caching the result of the first call. We need both `cached` and `cache`, because `null` is a valid value for `cache`.

- `ForwardingAttribDeclaration`

  #### Declaration

  `class `ForwardingAttribDeclaration`: dmd.attrib.AttribDeclaration;`

  Collection of declarations that stores foreach index variables in a local symbol table. Other symbols declared within are forwarded to another scope, like:

  #### Discussion

  static foreach (i; 0 .. 10) // loop variables for different indices do not conflict. { // this body is expanded into 10 ForwardingAttribDeclarations, where `i` has storage class STC.local mixin("enum x" ~ to!string(i) ~ " = i"); // ok, can access current loop variable }
  static foreach (i; 0.. 10) { pragma(msg, mixin("x" ~ to!string(i))); // ok, all 10 symbols are visible as they were forwarded to the global scope }
  static assert (!is(typeof(i))); // loop index variable is not visible outside of the static foreach loop
  A StaticForeachDeclaration generates one `ForwardingAttribDeclaration` for each expansion of its body. The AST of the `ForwardingAttribDeclaration` contains both the `static foreach`variables and the respective copy of the` static foreach` body. The functionality is achieved by using a ForwardingScopeDsymbol as the parent symbol for the generated declarations.

  - `newScope`

    #### Declaration

    `Scope* `newScope`(Scope* `sc`);`

    Use the ForwardingScopeDsymbol as the parent symbol for members.

  - `addMember`

    #### Declaration

    `void `addMember`(Scope* `sc`, ScopeDsymbol `sds`);`

    Lazily initializes the scope to forward to.

- `MixinDeclaration`

  #### Declaration

  `class `MixinDeclaration`: dmd.attrib.AttribDeclaration;`

  Mixin declarations, like: mixin("int x"); https://dlang.org/spec/module.html#mixin-declaration

- `UserAttributeDeclaration`

  #### Declaration

  `class `UserAttributeDeclaration`: dmd.attrib.AttribDeclaration;`

  User defined attributes look like: @foo(args, ...) @(args, ...)

  - `isGNUABITag`

    #### Declaration

    `static bool `isGNUABITag`(Expression `e`);`

    Check if the provided expression references `core.attribute.gnuAbiTag`

    #### Discussion

    This should be called after semantic has been run on the expression. Semantic on UDA happens in semantic2 (see `dmd.semantic2`).

    #### Parameters

    `Expression `e`` | Expression to check (usually from `UserAttributeDeclaration.atts`)

    #### Return Value

    `true` if the expression references the compiler-recognized `gnuAbiTag`

  - `checkGNUABITag`

    #### Declaration

    `static void `checkGNUABITag`(Dsymbol `sym`, LINK `linkage`);`

    Called from a symbol's semantic to check if `gnuAbiTag` UDA can be applied to them

    #### Discussion

    Directly emits an error if the UDA doesn't work with this symbol

    #### Parameters

    `Dsymbol `sym`` | symbol to check for `gnuAbiTag`
    `LINK `linkage`` | Linkage of the symbol (Declaration.link or sc.link)

- `isCoreUda`

  #### Declaration

  `bool `isCoreUda`(Dsymbol `sym`, Identifier `ident`);`

  Returns `true` if the given symbol is a symbol declared in `core.attribute` and has the given identifier.

  #### Discussion

  This is used to determine if a symbol is a UDA declared in `core.attribute`.

  #### Parameters

  `Dsymbol `sym`` | the symbol to check
  `Identifier `ident`` | the name of the expected UDA

- `foreachUda`

  #### Declaration

  `int `foreachUda`(Dsymbol `sym`, Scope* `sc`, int delegate(Expression) `dg`);`

  Iterates the UDAs attached to the given symbol.

  #### Parameters

  `Dsymbol `sym`` | the symbol to get the UDAs from
  `Scope* `sc`` | scope to use for semantic analysis of UDAs
  `int delegate(Expression) `dg`` | called once for each UDA

  #### Return Value

  If ``dg`` returns `!= 0`, stops the iteration and returns that value. Otherwise, returns 0.

- `foreachUdaNoSemantic`

  #### Declaration

  `int `foreachUdaNoSemantic`(Dsymbol `sym`, int delegate(Expression) `dg`);`

  Iterates the UDAs attached to the given symbol, without performing semantic analysis.

  #### Discussion

  Use this function instead of `foreachUda` if semantic analysis of ``sym`` is still in progress.

  #### Parameters

  `Dsymbol `sym`` | the symbol to get the UDAs from
  `int delegate(Expression) `dg`` | called once for each UDA

  #### Return Value

  If ``dg`` returns `!= 0`, stops the iteration and returns that value. Otherwise, returns 0.

)