/**
 * Defines declarations of various attributes.
 *
 * 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`)
 *
 * Copyright:   Copyright (C) 1999-2022 by The D Language Foundation, All Rights Reserved
 * Authors:     $(LINK2 https://www.digitalmars.com, Walter Bright)
 * License:     $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0)
 * Source:      $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/attrib.d, _attrib.d)
 * Documentation:  https://dlang.org/phobos/dmd_attrib.html
 * Coverage:    https://codecov.io/gh/dlang/dmd/src/master/src/dmd/attrib.d
 */

module dmd.attrib;

import dmd.aggregate;
import dmd.arraytypes;
import dmd.astenums;
import dmd.cond;
import dmd.declaration;
import dmd.dmodule;
import dmd.dscope;
import dmd.dsymbol;
import dmd.dsymbolsem : dsymbolSemantic;
import dmd.expression;
import dmd.expressionsem;
import dmd.func;
import dmd.globals;
import dmd.hdrgen : visibilityToBuffer;
import dmd.id;
import dmd.identifier;
import dmd.mtype;
import dmd.objc; // for objc.addSymbols
import dmd.common.outbuffer;
import dmd.root.array; // for each
import dmd.tokens;
import dmd.visitor;

/***********************************************************
 * Abstract attribute applied to Dsymbol's used as a common
 * ancestor for storage classes (StorageClassDeclaration),
 * linkage (LinkageDeclaration) and others.
 */
extern (C++) abstract class AttribDeclaration : Dsymbol
{
    Dsymbols* decl;     /// Dsymbol's affected by this AttribDeclaration

    extern (D) this(Dsymbols* decl)
    {
        this.decl = decl;
    }

    extern (D) this(const ref Loc loc, Identifier ident, Dsymbols* decl)
    {
        super(loc, ident);
        this.decl = decl;
    }

    Dsymbols* include(Scope* sc)
    {
        if (errors)
            return null;

        return decl;
    }

    /****************************************
     * 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.
     */
    extern (D) static Scope* createNewScope(Scope* sc, StorageClass stc, LINK linkage,
        CPPMANGLE cppmangle, Visibility visibility, int explicitVisibility,
        AlignDeclaration aligndecl, PragmaDeclaration inlining)
    {
        Scope* sc2 = sc;
        if (stc != sc.stc ||
            linkage != sc.linkage ||
            cppmangle != sc.cppmangle ||
            explicitVisibility != sc.explicitVisibility ||
            visibility != sc.visibility ||
            aligndecl !is sc.aligndecl ||
            inlining != sc.inlining)
        {
            // create new one for changes
            sc2 = sc.copy();
            sc2.stc = stc;
            sc2.linkage = linkage;
            sc2.cppmangle = cppmangle;
            sc2.visibility = visibility;
            sc2.explicitVisibility = explicitVisibility;
            sc2.aligndecl = aligndecl;
            sc2.inlining = inlining;
        }
        return sc2;
    }

    /****************************************
     * A hook point to supply scope for members.
     * addMember, setScope, importAll, semantic, semantic2 and semantic3 will use this.
     */
    Scope* newScope(Scope* sc)
    {
        return sc;
    }

    override void addMember(Scope* sc, ScopeDsymbol sds)
    {
        Dsymbols* d = include(sc);
        if (d)
        {
            Scope* sc2 = newScope(sc);
            d.foreachDsymbol( s => s.addMember(sc2, sds) );
            if (sc2 != sc)
                sc2.pop();
        }
    }

    override void setScope(Scope* sc)
    {
        Dsymbols* d = include(sc);
        //printf("\tAttribDeclaration::setScope '%s', d = %p\n",toChars(), d);
        if (d)
        {
            Scope* sc2 = newScope(sc);
            d.foreachDsymbol( s => s.setScope(sc2) );
            if (sc2 != sc)
                sc2.pop();
        }
    }

    override void importAll(Scope* sc)
    {
        Dsymbols* d = include(sc);
        //printf("\tAttribDeclaration::importAll '%s', d = %p\n", toChars(), d);
        if (d)
        {
            Scope* sc2 = newScope(sc);
            d.foreachDsymbol( s => s.importAll(sc2) );
            if (sc2 != sc)
                sc2.pop();
        }
    }

    override void addComment(const(char)* comment)
    {
        //printf("AttribDeclaration::addComment %s\n", comment);
        if (comment)
        {
            include(null).foreachDsymbol( s => s.addComment(comment) );
        }
    }

    override const(char)* kind() const
    {
        return "attribute";
    }

    override bool oneMember(Dsymbol* ps, Identifier ident)
    {
        Dsymbols* d = include(null);
        return Dsymbol.oneMembers(d, ps, ident);
    }

    override void setFieldOffset(AggregateDeclaration ad, ref FieldState fieldState, bool isunion)
    {
        include(null).foreachDsymbol( s => s.setFieldOffset(ad, fieldState, isunion) );
    }

    override final bool hasPointers()
    {
        return include(null).foreachDsymbol( (s) { return s.hasPointers(); } ) != 0;
    }

    override final bool hasStaticCtorOrDtor()
    {
        return include(null).foreachDsymbol( (s) { return s.hasStaticCtorOrDtor(); } ) != 0;
    }

    override final void checkCtorConstInit()
    {
        include(null).foreachDsymbol( s => s.checkCtorConstInit() );
    }

    /****************************************
     */
    override final void addLocalClass(ClassDeclarations* aclasses)
    {
        include(null).foreachDsymbol( s => s.addLocalClass(aclasses) );
    }

    override final void addObjcSymbols(ClassDeclarations* classes, ClassDeclarations* categories)
    {
        objc.addSymbols(this, classes, categories);
    }

    override final inout(AttribDeclaration) isAttribDeclaration() inout pure @safe
    {
        return this;
    }

    override void accept(Visitor v)
    {
        v.visit(this);
    }
}

/***********************************************************
 * Storage classes applied to Dsymbols, e.g. `const int i;`
 *
 * <stc> <decl...>
 */
extern (C++) class StorageClassDeclaration : AttribDeclaration
{
    StorageClass stc;

    extern (D) this(StorageClass stc, Dsymbols* decl)
    {
        super(decl);
        this.stc = stc;
    }

    override StorageClassDeclaration syntaxCopy(Dsymbol s)
    {
        assert(!s);
        return new StorageClassDeclaration(stc, Dsymbol.arraySyntaxCopy(decl));
    }

    override Scope* newScope(Scope* sc)
    {
        StorageClass scstc = sc.stc;
        /* These sets of storage classes are mutually exclusive,
         * so choose the innermost or most recent one.
         */
        if (stc & (STC.auto_ | STC.scope_ | STC.static_ | STC.extern_ | STC.manifest))
            scstc &= ~(STC.auto_ | STC.scope_ | STC.static_ | STC.extern_ | STC.manifest);
        if (stc & (STC.auto_ | STC.scope_ | STC.static_ | STC.manifest | STC.gshared))
            scstc &= ~(STC.auto_ | STC.scope_ | STC.static_ | STC.manifest | STC.gshared);
        if (stc & (STC.const_ | STC.immutable_ | STC.manifest))
            scstc &= ~(STC.const_ | STC.immutable_ | STC.manifest);
        if (stc & (STC.gshared | STC.shared_))
            scstc &= ~(STC.gshared | STC.shared_);
        if (stc & (STC.safe | STC.trusted | STC.system))
            scstc &= ~(STC.safe | STC.trusted | STC.system);
        scstc |= stc;
        //printf("scstc = x%llx\n", scstc);
        return createNewScope(sc, scstc, sc.linkage, sc.cppmangle,
            sc.visibility, sc.explicitVisibility, sc.aligndecl, sc.inlining);
    }

    override final bool oneMember(Dsymbol* ps, Identifier ident)
    {
        bool t = Dsymbol.oneMembers(decl, ps, ident);
        if (t && *ps)
        {
            /* This is to deal with the following case:
             * struct Tick {
             *   template to(T) { const T to() { ... } }
             * }
             * For eponymous function templates, the 'const' needs to get attached to 'to'
             * before the semantic analysis of 'to', so that template overloading based on the
             * 'this' pointer can be successful.
             */
            FuncDeclaration fd = (*ps).isFuncDeclaration();
            if (fd)
            {
                /* Use storage_class2 instead of storage_class otherwise when we do .di generation
                 * we'll wind up with 'const const' rather than 'const'.
                 */
                /* Don't think we need to worry about mutually exclusive storage classes here
                 */
                fd.storage_class2 |= stc;
            }
        }
        return t;
    }

    override void addMember(Scope* sc, ScopeDsymbol sds)
    {
        Dsymbols* d = include(sc);
        if (d)
        {
            Scope* sc2 = newScope(sc);

            d.foreachDsymbol( (s)
            {
                //printf("\taddMember %s to %s\n", s.toChars(), sds.toChars());
                // STC.local needs to be attached before the member is added to the scope (because it influences the parent symbol)
                if (auto decl = s.isDeclaration())
                {
                    decl.storage_class |= stc & STC.local;
                    if (auto sdecl = s.isStorageClassDeclaration()) // TODO: why is this not enough to deal with the nested case?
                    {
                        sdecl.stc |= stc & STC.local;
                    }
                }
                s.addMember(sc2, sds);
            });

            if (sc2 != sc)
                sc2.pop();
        }

    }

    override inout(StorageClassDeclaration) isStorageClassDeclaration() inout
    {
        return this;
    }

    override void accept(Visitor v)
    {
        v.visit(this);
    }
}

/***********************************************************
 * 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_)
 *
 * `deprecated(<msg>) <decl...>`
 */
extern (C++) final class DeprecatedDeclaration : StorageClassDeclaration
{
    Expression msg;         /// deprecation message
    const(char)* msgstr;    /// cached string representation of msg

    extern (D) this(Expression msg, Dsymbols* decl)
    {
        super(STC.deprecated_, decl);
        this.msg = msg;
    }

    override DeprecatedDeclaration syntaxCopy(Dsymbol s)
    {
        assert(!s);
        return new DeprecatedDeclaration(msg.syntaxCopy(), Dsymbol.arraySyntaxCopy(decl));
    }

    /**
     * Provides a new scope with `STC.deprecated_` and `Scope.depdecl` set
     *
     * Calls `StorageClassDeclaration.newScope` (as it must be called or copied
     * in any function overriding `newScope`), then set the `Scope`'s depdecl.
     *
     * Returns:
     *   Always a new scope, to use for this `DeprecatedDeclaration`'s members.
     */
    override Scope* newScope(Scope* sc)
    {
        auto scx = super.newScope(sc);
        // The enclosing scope is deprecated as well
        if (scx == sc)
            scx = sc.push();
        scx.depdecl = this;
        return scx;
    }

    override void setScope(Scope* sc)
    {
        //printf("DeprecatedDeclaration::setScope() %p\n", this);
        if (decl)
            Dsymbol.setScope(sc); // for forward reference
        return AttribDeclaration.setScope(sc);
    }

    override void accept(Visitor v)
    {
        v.visit(this);
    }
}

/***********************************************************
 * Linkage attribute applied to Dsymbols, e.g.
 * `extern(C) void foo()`.
 *
 * `extern(<linkage>) <decl...>`
 */
extern (C++) final class LinkDeclaration : AttribDeclaration
{
    LINK linkage; /// either explicitly set or `default_`

    extern (D) this(const ref Loc loc, LINK linkage, Dsymbols* decl)
    {
        super(loc, null, decl);
        //printf("LinkDeclaration(linkage = %d, decl = %p)\n", linkage, decl);
        this.linkage = linkage;
    }

    static LinkDeclaration create(const ref Loc loc, LINK p, Dsymbols* decl)
    {
        return new LinkDeclaration(loc, p, decl);
    }

    override LinkDeclaration syntaxCopy(Dsymbol s)
    {
        assert(!s);
        return new LinkDeclaration(loc, linkage, Dsymbol.arraySyntaxCopy(decl));
    }

    override Scope* newScope(Scope* sc)
    {
        return createNewScope(sc, sc.stc, this.linkage, sc.cppmangle, sc.visibility, sc.explicitVisibility,
            sc.aligndecl, sc.inlining);
    }

    override const(char)* toChars() const
    {
        return toString().ptr;
    }

    extern(D) override const(char)[] toString() const
    {
        return "extern ()";
    }

    override void accept(Visitor v)
    {
        v.visit(this);
    }
}

/***********************************************************
 * 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.
 *
 * `extern(C++, <cppmangle>) <decl...>`
 */
extern (C++) final class CPPMangleDeclaration : AttribDeclaration
{
    CPPMANGLE cppmangle;

    extern (D) this(const ref Loc loc, CPPMANGLE cppmangle, Dsymbols* decl)
    {
        super(loc, null, decl);
        //printf("CPPMangleDeclaration(cppmangle = %d, decl = %p)\n", cppmangle, decl);
        this.cppmangle = cppmangle;
    }

    override CPPMangleDeclaration syntaxCopy(Dsymbol s)
    {
        assert(!s);
        return new CPPMangleDeclaration(loc, cppmangle, Dsymbol.arraySyntaxCopy(decl));
    }

    override Scope* newScope(Scope* sc)
    {
        return createNewScope(sc, sc.stc, LINK.cpp, cppmangle, sc.visibility, sc.explicitVisibility,
            sc.aligndecl, sc.inlining);
    }

    override void setScope(Scope* sc)
    {
        if (decl)
            Dsymbol.setScope(sc); // for forward reference
        return AttribDeclaration.setScope(sc);
    }

    override const(char)* toChars() const
    {
        return toString().ptr;
    }

    extern(D) override const(char)[] toString() const
    {
        return "extern ()";
    }

    override void accept(Visitor v)
    {
        v.visit(this);
    }
}

/**
 * A node to represent an `extern(C++)` namespace attribute
 *
 * 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"`.
 */
extern (C++) final class CPPNamespaceDeclaration : AttribDeclaration
{
    /// CTFE-able expression, resolving to `TupleExp` or `StringExp`
    Expression exp;

    extern (D) this(const ref Loc loc, Identifier ident, Dsymbols* decl)
    {
        super(loc, ident, decl);
    }

    extern (D) this(const ref Loc loc, Expression exp, Dsymbols* decl)
    {
        super(loc, null, decl);
        this.exp = exp;
    }

    extern (D) this(const ref Loc loc, Identifier ident, Expression exp, Dsymbols* decl,
                    CPPNamespaceDeclaration parent)
    {
        super(loc, ident, decl);
        this.exp = exp;
        this.cppnamespace = parent;
    }

    override CPPNamespaceDeclaration syntaxCopy(Dsymbol s)
    {
        assert(!s);
        return new CPPNamespaceDeclaration(
            this.loc, this.ident, this.exp, Dsymbol.arraySyntaxCopy(this.decl), this.cppnamespace);
    }

    /**
     * Returns:
     *   A copy of the parent scope, with `this` as `namespace` and C++ linkage
     */
    override Scope* newScope(Scope* sc)
    {
        auto scx = sc.copy();
        scx.linkage = LINK.cpp;
        scx.namespace = this;
        return scx;
    }

    override const(char)* toChars() const
    {
        return toString().ptr;
    }

    extern(D) override const(char)[] toString() const
    {
        return "extern (C++, `namespace`)";
    }

    override void accept(Visitor v)
    {
        v.visit(this);
    }

    override inout(CPPNamespaceDeclaration) isCPPNamespaceDeclaration() inout { return this; }
}

/***********************************************************
 * Visibility declaration for Dsymbols, e.g. `public int i;`
 *
 * `<visibility> <decl...>` or
 * `package(<pkg_identifiers>) <decl...>` if `pkg_identifiers !is null`
 */
extern (C++) final class VisibilityDeclaration : AttribDeclaration
{
    Visibility visibility;          /// the visibility
    Identifier[] pkg_identifiers;   /// identifiers for `package(foo.bar)` or null

    /**
     * Params:
     *  loc = source location of attribute token
     *  visibility = visibility attribute data
     *  decl = declarations which are affected by this visibility attribute
     */
    extern (D) this(const ref Loc loc, Visibility visibility, Dsymbols* decl)
    {
        super(loc, null, decl);
        this.visibility = visibility;
        //printf("decl = %p\n", decl);
    }

    /**
     * Params:
     *  loc = source location of attribute token
     *  pkg_identifiers = list of identifiers for a qualified package name
     *  decl = declarations which are affected by this visibility attribute
     */
    extern (D) this(const ref Loc loc, Identifier[] pkg_identifiers, Dsymbols* decl)
    {
        super(loc, null, decl);
        this.visibility.kind = Visibility.Kind.package_;
        this.pkg_identifiers = pkg_identifiers;
        if (pkg_identifiers.length > 0)
        {
            Dsymbol tmp;
            Package.resolve(pkg_identifiers, &tmp, null);
            visibility.pkg = tmp ? tmp.isPackage() : null;
        }
    }

    override VisibilityDeclaration syntaxCopy(Dsymbol s)
    {
        assert(!s);

        if (visibility.kind == Visibility.Kind.package_)
            return new VisibilityDeclaration(this.loc, pkg_identifiers, Dsymbol.arraySyntaxCopy(decl));
        else
            return new VisibilityDeclaration(this.loc, visibility, Dsymbol.arraySyntaxCopy(decl));
    }

    override Scope* newScope(Scope* sc)
    {
        if (pkg_identifiers)
            dsymbolSemantic(this, sc);
        return createNewScope(sc, sc.stc, sc.linkage, sc.cppmangle, this.visibility, 1, sc.aligndecl, sc.inlining);
    }

    override void addMember(Scope* sc, ScopeDsymbol sds)
    {
        if (pkg_identifiers)
        {
            Dsymbol tmp;
            Package.resolve(pkg_identifiers, &tmp, null);
            visibility.pkg = tmp ? tmp.isPackage() : null;
            pkg_identifiers = null;
        }
        if (visibility.kind == Visibility.Kind.package_ && visibility.pkg && sc._module)
        {
            Module m = sc._module;

            // While isAncestorPackageOf does an equality check, the fix for issue 17441 adds a check to see if
            // each package's .isModule() properites are equal.
            //
            // Properties generated from `package(foo)` i.e. visibility.pkg have .isModule() == null.
            // This breaks package declarations of the package in question if they are declared in
            // the same package.d file, which _do_ have a module associated with them, and hence a non-null
            // isModule()
            if (!m.isPackage() || !visibility.pkg.ident.equals(m.isPackage().ident))
            {
                Package pkg = m.parent ? m.parent.isPackage() : null;
                if (!pkg || !visibility.pkg.isAncestorPackageOf(pkg))
                    error("does not bind to one of ancestor packages of module `%s`", m.toPrettyChars(true));
            }
        }
        return AttribDeclaration.addMember(sc, sds);
    }

    override const(char)* kind() const
    {
        return "visibility attribute";
    }

    override const(char)* toPrettyChars(bool)
    {
        assert(visibility.kind > Visibility.Kind.undefined);
        OutBuffer buf;
        visibilityToBuffer(&buf, visibility);
        return buf.extractChars();
    }

    override inout(VisibilityDeclaration) isVisibilityDeclaration() inout
    {
        return this;
    }

    override void accept(Visitor v)
    {
        v.visit(this);
    }
}

/***********************************************************
 * Alignment attribute for aggregates, members and variables.
 *
 * `align(<ealign>) <decl...>` or
 * `align <decl...>` if `ealign` is null
 */
extern (C++) final class AlignDeclaration : AttribDeclaration
{
    Expressions* exps;                              /// Expression(s) yielding the desired alignment,
                                                    /// 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)
    structalign_t salign;


    extern (D) this(const ref Loc loc, Expression exp, Dsymbols* decl)
    {
        super(loc, null, decl);
        if (exp)
        {
            exps = new Expressions();
            exps.push(exp);
        }
    }

    extern (D) this(const ref Loc loc, Expressions* exps, Dsymbols* decl)
    {
        super(loc, null, decl);
        this.exps = exps;
    }

    extern (D) this(const ref Loc loc, structalign_t salign, Dsymbols* decl)
    {
        super(loc, null, decl);
        this.salign = salign;
    }

    override AlignDeclaration syntaxCopy(Dsymbol s)
    {
        assert(!s);
        return new AlignDeclaration(loc,
            Expression.arraySyntaxCopy(exps),
            Dsymbol.arraySyntaxCopy(decl));
    }

    override Scope* newScope(Scope* sc)
    {
        return createNewScope(sc, sc.stc, sc.linkage, sc.cppmangle, sc.visibility, sc.explicitVisibility, this, sc.inlining);
    }

    override void accept(Visitor v)
    {
        v.visit(this);
    }
}

/***********************************************************
 * An anonymous struct/union (defined by `isunion`).
 */
extern (C++) final class AnonDeclaration : AttribDeclaration
{
    bool isunion;           /// whether it's a union
    int sem;                /// 1 if successful semantic()
    uint anonoffset;        /// offset of anonymous struct
    uint anonstructsize;    /// size of anonymous struct
    uint anonalignsize;     /// size of anonymous struct for alignment purposes

    extern (D) this(const ref Loc loc, bool isunion, Dsymbols* decl)
    {
        super(loc, null, decl);
        this.isunion = isunion;
    }

    override AnonDeclaration syntaxCopy(Dsymbol s)
    {
        assert(!s);
        return new AnonDeclaration(loc, isunion, Dsymbol.arraySyntaxCopy(decl));
    }

    override void setScope(Scope* sc)
    {
        if (decl)
            Dsymbol.setScope(sc);
        return AttribDeclaration.setScope(sc);
    }

    override void setFieldOffset(AggregateDeclaration ad, ref FieldState fieldState, bool isunion)
    {
        //printf("\tAnonDeclaration::setFieldOffset %s %p\n", isunion ? "union" : "struct", this);
        if (decl)
        {
            /* This works by treating an AnonDeclaration as an aggregate 'member',
             * so in order to place that member we need to compute the member's
             * size and alignment.
             */
            size_t fieldstart = ad.fields.dim;

            /* Hackishly hijack ad's structsize and alignsize fields
             * for use in our fake anon aggregate member.
             */
            uint savestructsize = ad.structsize;
            uint savealignsize = ad.alignsize;
            ad.structsize = 0;
            ad.alignsize = 0;

            FieldState fs;
            decl.foreachDsymbol( (s)
            {
                s.setFieldOffset(ad, fs, this.isunion);
                if (this.isunion)
                    fs.offset = 0;
            });

            /* https://issues.dlang.org/show_bug.cgi?id=13613
             * If the fields in this.members had been already
             * added in ad.fields, just update *poffset for the subsequent
             * field offset calculation.
             */
            if (fieldstart == ad.fields.dim)
            {
                ad.structsize = savestructsize;
                ad.alignsize = savealignsize;
                fieldState.offset = ad.structsize;
                return;
            }

            anonstructsize = ad.structsize;
            anonalignsize = ad.alignsize;
            ad.structsize = savestructsize;
            ad.alignsize = savealignsize;

            // 0 sized structs are set to 1 byte
            if (anonstructsize == 0)
            {
                anonstructsize = 1;
                anonalignsize = 1;
            }

            assert(_scope);
            auto alignment = _scope.alignment();

            /* Given the anon 'member's size and alignment,
             * go ahead and place it.
             */
            anonoffset = AggregateDeclaration.placeField(
                &fieldState.offset,
                anonstructsize, anonalignsize, alignment,
                &ad.structsize, &ad.alignsize,
                isunion);

            // Add to the anon fields the base offset of this anonymous aggregate
            //printf("anon fields, anonoffset = %d\n", anonoffset);
            foreach (const i; fieldstart .. ad.fields.dim)
            {
                VarDeclaration v = ad.fields[i];
                //printf("\t[%d] %s %d\n", i, v.toChars(), v.offset);
                v.offset += anonoffset;
            }
        }
    }

    override const(char)* kind() const
    {
        return (isunion ? "anonymous union" : "anonymous struct");
    }

    override inout(AnonDeclaration) isAnonDeclaration() inout
    {
        return this;
    }

    override void accept(Visitor v)
    {
        v.visit(this);
    }
}

/***********************************************************
 * Pragma applied to Dsymbols, e.g. `pragma(inline, true) void foo`,
 * but not PragmaStatement's like `pragma(msg, "hello");`.
 *
 * pragma(<ident>, <args>)
 */
extern (C++) final class PragmaDeclaration : AttribDeclaration
{
    Expressions* args;      /// parameters of this pragma

    extern (D) this(const ref Loc loc, Identifier ident, Expressions* args, Dsymbols* decl)
    {
        super(loc, ident, decl);
        this.args = args;
    }

    override PragmaDeclaration syntaxCopy(Dsymbol s)
    {
        //printf("PragmaDeclaration::syntaxCopy(%s)\n", toChars());
        assert(!s);
        return new PragmaDeclaration(loc, ident, Expression.arraySyntaxCopy(args), Dsymbol.arraySyntaxCopy(decl));
    }

    override Scope* newScope(Scope* sc)
    {
        if (ident == Id.Pinline)
        {
            // We keep track of this pragma inside scopes,
            // then it's evaluated on demand in function semantic
            return createNewScope(sc, sc.stc, sc.linkage, sc.cppmangle, sc.visibility, sc.explicitVisibility, sc.aligndecl, this);
        }
        if (ident == Id.printf || ident == Id.scanf)
        {
            auto sc2 = sc.push();

            if (ident == Id.printf)
                // Override previous setting, never let both be set
                sc2.flags = (sc2.flags & ~SCOPE.scanf) | SCOPE.printf;
            else
                sc2.flags = (sc2.flags & ~SCOPE.printf) | SCOPE.scanf;

            return sc2;
        }
        return sc;
    }

    PINLINE evalPragmaInline(Scope* sc)
    {
        if (!args || args.dim == 0)
            return PINLINE.default_;

        Expression e = (*args)[0];
        if (!e.type)
        {

            sc = sc.startCTFE();
            e = e.expressionSemantic(sc);
            e = resolveProperties(sc, e);
            sc = sc.endCTFE();
            e = e.ctfeInterpret();
            e = e.toBoolean(sc);
            if (e.isErrorExp())
                error("pragma(`inline`, `true` or `false`) expected, not `%s`", (*args)[0].toChars());
            (*args)[0] = e;
        }

        const opt = e.toBool();
        if (opt.isEmpty())
            return PINLINE.default_;
        else if (opt.get())
            return PINLINE.always;
        else
            return PINLINE.never;
    }

    override const(char)* kind() const
    {
        return "pragma";
    }

    override void accept(Visitor v)
    {
        v.visit(this);
    }
}

/***********************************************************
 * A conditional compilation declaration, used for `version`
 * / `debug` and specialized for `static if`.
 *
 * <condition> { <decl...> } else { <elsedecl> }
 */
extern (C++) class ConditionalDeclaration : AttribDeclaration
{
    Condition condition;    /// condition deciding whether decl or elsedecl applies
    Dsymbols* elsedecl;     /// array of Dsymbol's for else block

    extern (D) this(const ref Loc loc, Condition condition, Dsymbols* decl, Dsymbols* elsedecl)
    {
        super(loc, null, decl);
        //printf("ConditionalDeclaration::ConditionalDeclaration()\n");
        this.condition = condition;
        this.elsedecl = elsedecl;
    }

    override ConditionalDeclaration syntaxCopy(Dsymbol s)
    {
        assert(!s);
        return new ConditionalDeclaration(loc, condition.syntaxCopy(), Dsymbol.arraySyntaxCopy(decl), Dsymbol.arraySyntaxCopy(elsedecl));
    }

    override final bool oneMember(Dsymbol* ps, Identifier ident)
    {
        //printf("ConditionalDeclaration::oneMember(), inc = %d\n", condition.inc);
        if (condition.inc != Include.notComputed)
        {
            Dsymbols* d = condition.include(null) ? decl : elsedecl;
            return Dsymbol.oneMembers(d, ps, ident);
        }
        else
        {
            bool res = (Dsymbol.oneMembers(decl, ps, ident) && *ps is null && Dsymbol.oneMembers(elsedecl, ps, ident) && *ps is null);
            *ps = null;
            return res;
        }
    }

    // Decide if 'then' or 'else' code should be included
    override Dsymbols* include(Scope* sc)
    {
        //printf("ConditionalDeclaration::include(sc = %p) scope = %p\n", sc, _scope);

        if (errors)
            return null;

        assert(condition);
        return condition.include(_scope ? _scope : sc) ? decl : elsedecl;
    }

    override final void addComment(const(char)* comment)
    {
        /* Because addComment is called by the parser, if we called
         * include() it would define a version before it was used.
         * But it's no problem to drill down to both decl and elsedecl,
         * so that's the workaround.
         */
        if (comment)
        {
            decl    .foreachDsymbol( s => s.addComment(comment) );
            elsedecl.foreachDsymbol( s => s.addComment(comment) );
        }
    }

    override void setScope(Scope* sc)
    {
        include(sc).foreachDsymbol( s => s.setScope(sc) );
    }

    override void accept(Visitor v)
    {
        v.visit(this);
    }
}

/***********************************************************
 * `<scopesym> {
 *      static if (<condition>) { <decl> } else { <elsedecl> }
 * }`
 */
extern (C++) final class StaticIfDeclaration : ConditionalDeclaration
{
    ScopeDsymbol scopesym;          /// enclosing symbol (e.g. module) where symbols will be inserted
    private bool addisdone = false; /// true if members have been added to scope
    private bool onStack = false;   /// true if a call to `include` is currently active

    extern (D) this(const ref Loc loc, Condition condition, Dsymbols* decl, Dsymbols* elsedecl)
    {
        super(loc, condition, decl, elsedecl);
        //printf("StaticIfDeclaration::StaticIfDeclaration()\n");
    }

    override StaticIfDeclaration syntaxCopy(Dsymbol s)
    {
        assert(!s);
        return new StaticIfDeclaration(loc, condition.syntaxCopy(), Dsymbol.arraySyntaxCopy(decl), Dsymbol.arraySyntaxCopy(elsedecl));
    }

    /****************************************
     * Different from other AttribDeclaration subclasses, include() call requires
     * the completion of addMember and setScope phases.
     */
    override Dsymbols* include(Scope* sc)
    {
        //printf("StaticIfDeclaration::include(sc = %p) scope = %p\n", sc, _scope);

        if (errors || onStack)
            return null;
        onStack = true;
        scope(exit) onStack = false;

        if (sc && condition.inc == Include.notComputed)
        {
            assert(scopesym); // addMember is already done
            assert(_scope); // setScope is already done
            Dsymbols* d = ConditionalDeclaration.include(_scope);
            if (d && !addisdone)
            {
                // Add members lazily.
                d.foreachDsymbol( s => s.addMember(_scope, scopesym) );

                // Set the member scopes lazily.
                d.foreachDsymbol( s => s.setScope(_scope) );

                addisdone = true;
            }
            return d;
        }
        else
        {
            return ConditionalDeclaration.include(sc);
        }
    }

    override void addMember(Scope* sc, ScopeDsymbol sds)
    {
        //printf("StaticIfDeclaration::addMember() '%s'\n", toChars());
        /* This is deferred until the condition evaluated later (by the include() call),
         * so that expressions in the condition can refer to declarations
         * in the same scope, such as:
         *
         * template Foo(int i)
         * {
         *     const int j = i + 1;
         *     static if (j == 3)
         *         const int k;
         * }
         */
        this.scopesym = sds;
    }

    override void setScope(Scope* sc)
    {
        // do not evaluate condition before semantic pass
        // But do set the scope, in case we need it for forward referencing
        Dsymbol.setScope(sc);
    }

    override void importAll(Scope* sc)
    {
        // do not evaluate condition before semantic pass
    }

    override const(char)* kind() const
    {
        return "static if";
    }

    override void accept(Visitor v)
    {
        v.visit(this);
    }
}

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

extern (C++) final class StaticForeachDeclaration : AttribDeclaration
{
    StaticForeach sfe; /// contains `static foreach` expansion logic

    ScopeDsymbol scopesym; /// cached enclosing scope (mimics `static if` declaration)

    /++
     `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`.
     +/
    bool onStack = false;
    bool cached = false;
    Dsymbols* cache = null;

    extern (D) this(StaticForeach sfe, Dsymbols* decl)
    {
        super(sfe.loc, null, decl);
        this.sfe = sfe;
    }

    override StaticForeachDeclaration syntaxCopy(Dsymbol s)
    {
        assert(!s);
        return new StaticForeachDeclaration(
            sfe.syntaxCopy(),
            Dsymbol.arraySyntaxCopy(decl));
    }

    override bool oneMember(Dsymbol* ps, Identifier ident)
    {
        // Required to support IFTI on a template that contains a
        // `static foreach` declaration.  `super.oneMember` calls
        // include with a `null` scope.  As `static foreach` requires
        // the scope for expansion, `oneMember` can only return a
        // precise result once `static foreach` has been expanded.
        if (cached)
        {
            return super.oneMember(ps, ident);
        }
        *ps = null; // a `static foreach` declaration may in general expand to multiple symbols
        return false;
    }

    override Dsymbols* include(Scope* sc)
    {
        if (errors || onStack)
            return null;
        if (cached)
        {
            assert(!onStack);
            return cache;
        }
        onStack = true;
        scope(exit) onStack = false;

        if (_scope)
        {
            sfe.prepare(_scope); // lower static foreach aggregate
        }
        if (!sfe.ready())
        {
            return null; // TODO: ok?
        }

        // expand static foreach
        import dmd.statementsem: makeTupleForeach;
        Dsymbols* d = makeTupleForeach(_scope, true, true, sfe.aggrfe, decl, sfe.needExpansion).decl;
        if (d) // process generated declarations
        {
            // Add members lazily.
            d.foreachDsymbol( s => s.addMember(_scope, scopesym) );

            // Set the member scopes lazily.
            d.foreachDsymbol( s => s.setScope(_scope) );
        }
        cached = true;
        cache = d;
        return d;
    }

    override void addMember(Scope* sc, ScopeDsymbol sds)
    {
        // used only for caching the enclosing symbol
        this.scopesym = sds;
    }

    override void addComment(const(char)* comment)
    {
        // do nothing
        // change this to give semantics to documentation comments on static foreach declarations
    }

    override void setScope(Scope* sc)
    {
        // do not evaluate condition before semantic pass
        // But do set the scope, in case we need it for forward referencing
        Dsymbol.setScope(sc);
    }

    override void importAll(Scope* sc)
    {
        // do not evaluate aggregate before semantic pass
    }

    override const(char)* kind() const
    {
        return "static foreach";
    }

    override void accept(Visitor v)
    {
        v.visit(this);
    }
}

/***********************************************************
 * Collection of declarations that stores foreach index variables in a
 * local symbol table.  Other symbols declared within are forwarded to
 * another scope, like:
 *
 *      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.
 */

extern(C++) final class ForwardingAttribDeclaration: AttribDeclaration
{
    ForwardingScopeDsymbol sym = null;

    this(Dsymbols* decl)
    {
        super(decl);
        sym = new ForwardingScopeDsymbol(null);
        sym.symtab = new DsymbolTable();
    }

    /**************************************
     * Use the ForwardingScopeDsymbol as the parent symbol for members.
     */
    override Scope* newScope(Scope* sc)
    {
        return sc.push(sym);
    }

    /***************************************
     * Lazily initializes the scope to forward to.
     */
    override void addMember(Scope* sc, ScopeDsymbol sds)
    {
        parent = sym.parent = sym.forward = sds;
        return super.addMember(sc, sym);
    }

    override inout(ForwardingAttribDeclaration) isForwardingAttribDeclaration() inout
    {
        return this;
    }

    override void accept(Visitor v)
    {
        v.visit(this);
    }
}


/***********************************************************
 * Mixin declarations, like:
 *      mixin("int x");
 * https://dlang.org/spec/module.html#mixin-declaration
 */
extern (C++) final class CompileDeclaration : AttribDeclaration
{
    Expressions* exps;
    ScopeDsymbol scopesym;
    bool compiled;

    extern (D) this(const ref Loc loc, Expressions* exps)
    {
        super(loc, null, null);
        //printf("CompileDeclaration(loc = %d)\n", loc.linnum);
        this.exps = exps;
    }

    override CompileDeclaration syntaxCopy(Dsymbol s)
    {
        //printf("CompileDeclaration::syntaxCopy('%s')\n", toChars());
        return new CompileDeclaration(loc, Expression.arraySyntaxCopy(exps));
    }

    override void addMember(Scope* sc, ScopeDsymbol sds)
    {
        //printf("CompileDeclaration::addMember(sc = %p, sds = %p, memnum = %d)\n", sc, sds, memnum);
        this.scopesym = sds;
    }

    override void setScope(Scope* sc)
    {
        Dsymbol.setScope(sc);
    }

    override const(char)* kind() const
    {
        return "mixin";
    }

    override inout(CompileDeclaration) isCompileDeclaration() inout
    {
        return this;
    }

    override void accept(Visitor v)
    {
        v.visit(this);
    }
}

/***********************************************************
 * User defined attributes look like:
 *      @foo(args, ...)
 *      @(args, ...)
 */
extern (C++) final class UserAttributeDeclaration : AttribDeclaration
{
    Expressions* atts;

    extern (D) this(Expressions* atts, Dsymbols* decl)
    {
        super(decl);
        this.atts = atts;
    }

    override UserAttributeDeclaration syntaxCopy(Dsymbol s)
    {
        //printf("UserAttributeDeclaration::syntaxCopy('%s')\n", toChars());
        assert(!s);
        return new UserAttributeDeclaration(Expression.arraySyntaxCopy(this.atts), Dsymbol.arraySyntaxCopy(decl));
    }

    override Scope* newScope(Scope* sc)
    {
        Scope* sc2 = sc;
        if (atts && atts.dim)
        {
            // create new one for changes
            sc2 = sc.copy();
            sc2.userAttribDecl = this;
        }
        return sc2;
    }

    override void setScope(Scope* sc)
    {
        //printf("UserAttributeDeclaration::setScope() %p\n", this);
        if (decl)
            Dsymbol.setScope(sc); // for forward reference of UDAs
        return AttribDeclaration.setScope(sc);
    }

    extern (D) static Expressions* concat(Expressions* udas1, Expressions* udas2)
    {
        Expressions* udas;
        if (!udas1 || udas1.dim == 0)
            udas = udas2;
        else if (!udas2 || udas2.dim == 0)
            udas = udas1;
        else
        {
            /* Create a new tuple that combines them
             * (do not append to left operand, as this is a copy-on-write operation)
             */
            udas = new Expressions(2);
            (*udas)[0] = new TupleExp(Loc.initial, udas1);
            (*udas)[1] = new TupleExp(Loc.initial, udas2);
        }
        return udas;
    }

    Expressions* getAttributes()
    {
        if (auto sc = _scope)
        {
            _scope = null;
            arrayExpressionSemantic(atts, sc);
        }
        auto exps = new Expressions();
        if (userAttribDecl && userAttribDecl !is this)
            exps.push(new TupleExp(Loc.initial, userAttribDecl.getAttributes()));
        if (atts && atts.dim)
            exps.push(new TupleExp(Loc.initial, atts));
        return exps;
    }

    override const(char)* kind() const
    {
        return "UserAttribute";
    }

    override void accept(Visitor v)
    {
        v.visit(this);
    }

    /**
     * Check if the provided expression references `core.attribute.gnuAbiTag`
     *
     * This should be called after semantic has been run on the expression.
     * Semantic on UDA happens in semantic2 (see `dmd.semantic2`).
     *
     * Params:
     *   e = Expression to check (usually from `UserAttributeDeclaration.atts`)
     *
     * Returns:
     *   `true` if the expression references the compiler-recognized `gnuAbiTag`
     */
    static bool isGNUABITag(Expression e)
    {
        if (global.params.cplusplus < CppStdRevision.cpp11)
            return false;

        auto ts = e.type ? e.type.isTypeStruct() : null;
        if (!ts)
            return false;
        if (ts.sym.ident != Id.udaGNUAbiTag || !ts.sym.parent)
            return false;
        // Can only be defined in druntime
        Module m = ts.sym.parent.isModule();
        if (!m || !m.isCoreModule(Id.attribute))
            return false;
        return true;
    }

    /**
     * Called from a symbol's semantic to check if `gnuAbiTag` UDA
     * can be applied to them
     *
     * Directly emits an error if the UDA doesn't work with this symbol
     *
     * Params:
     *   sym = symbol to check for `gnuAbiTag`
     *   linkage = Linkage of the symbol (Declaration.link or sc.link)
     */
    static void checkGNUABITag(Dsymbol sym, LINK linkage)
    {
        if (global.params.cplusplus < CppStdRevision.cpp11)
            return;

        foreachUdaNoSemantic(sym, (exp) {
            if (isGNUABITag(exp))
            {
                if (sym.isCPPNamespaceDeclaration() || sym.isNspace())
                {
                    exp.error("`@%s` cannot be applied to namespaces", Id.udaGNUAbiTag.toChars());
                    sym.errors = true;
                }
                else if (linkage != LINK.cpp)
                {
                    exp.error("`@%s` can only apply to C++ symbols", Id.udaGNUAbiTag.toChars());
                    sym.errors = true;
                }
                // Only one `@gnuAbiTag` is allowed by semantic2
                return 1; // break
            }
            return 0; // continue
        });
    }
}

/**
 * Returns `true` if the given symbol is a symbol declared in
 * `core.attribute` and has the given identifier.
 *
 * This is used to determine if a symbol is a UDA declared in
 * `core.attribute`.
 *
 * Params:
 *  sym = the symbol to check
 *  ident = the name of the expected UDA
 */
bool isCoreUda(Dsymbol sym, Identifier ident)
{
    if (sym.ident != ident || !sym.parent)
        return false;

    auto _module = sym.parent.isModule();
    return _module && _module.isCoreModule(Id.attribute);
}

/**
 * Iterates the UDAs attached to the given symbol.
 *
 * Params:
 *  sym = the symbol to get the UDAs from
 *  sc = scope to use for semantic analysis of UDAs
 *  dg = called once for each UDA
 *
 * Returns:
 *  If `dg` returns `!= 0`, stops the iteration and returns that value.
 *  Otherwise, returns 0.
 */
int foreachUda(Dsymbol sym, Scope* sc, int delegate(Expression) dg)
{
    if (!sym.userAttribDecl)
        return 0;

    auto udas = sym.userAttribDecl.getAttributes();
    arrayExpressionSemantic(udas, sc, true);

    return udas.each!((uda) {
        if (!uda.isTupleExp())
            return 0;

        auto exps = uda.isTupleExp().exps;

        return exps.each!((e) {
            assert(e);

            if (auto result = dg(e))
                return result;

            return 0;
        });
    });
}

/**
 * Iterates the UDAs attached to the given symbol, without performing semantic
 * analysis.
 *
 * Use this function instead of `foreachUda` if semantic analysis of `sym` is
 * still in progress.
 *
 * Params:
 *  sym = the symbol to get the UDAs from
 *  dg = called once for each UDA
 *
 * Returns:
 *  If `dg` returns `!= 0`, stops the iteration and returns that value.
 *  Otherwise, returns 0.
 */
int foreachUdaNoSemantic(Dsymbol sym, int delegate(Expression) dg)
{
    if (sym.userAttribDecl is null || sym.userAttribDecl.atts is null)
        return 0;

    foreach (exp; *sym.userAttribDecl.atts)
    {
        if (auto result = dg(exp))
            return result;
    }

    return 0;
}
