www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.bugs - [Issue 14038] New: [REG2.067a] Non-mutable AA initialization

https://issues.dlang.org/show_bug.cgi?id=14038

          Issue ID: 14038
           Summary: [REG2.067a] Non-mutable AA initialization segfaults in
                    runtime
           Product: D
           Version: D2
          Hardware: All
                OS: All
            Status: NEW
          Keywords: wrong-code
          Severity: regression
          Priority: P1
         Component: DMD
          Assignee: nobody puremagic.com
          Reporter: k.hara.pg gmail.com

From: http://forum.dlang.org/thread/vtenbjmktplcxxmbyurt forum.dlang.org

With git-head, this code segfaults in runtime.

    static immutable words = [ `zero`, `one`, `two` ];

    static immutable ubyte[string] wordsAA;

    static this()
    {
        foreach (ubyte i, e; words) { wordsAA[e] = i; }
    }

The regression had introduced by the combination of:
https://github.com/D-Programming-Language/dmd/pull/4159
https://github.com/D-Programming-Language/druntime/pull/1037

The core issue is in dmd e2ir.c around lien 4570.

        void visit(IndexExp *ie)
        {
            ...
            Type *t1 = ie->e1->type->toBasetype();
            if (t1->ty == Taarray)
            {
                // set to:
                //      *aaGetY(aa, aati, valuesize, &key);
                // or
                //      *aaGetRvalueX(aa, keyti, valuesize, &key);

                TypeAArray *taa = (TypeAArray *)t1;
                ...
                elem* ti;
                if (ie->modifiable)
                {
                    n1 = el_una(OPaddr, TYnptr, n1);
                    s = aaGetSymbol(taa, "GetY", 1);
                    ti = toElem(getInternalTypeInfo(taa, NULL), irs);   // <---
                }
                else
                {
                    s = aaGetSymbol(taa, "GetRvalueX", 1);
                    ti = toElem(getInternalTypeInfo(taa->index, NULL), irs);
                }
                //printf("taa->index = %s\n", taa->index->toChars());
                //printf("ti:\n"); elem_print(ti);
                elem* ep = el_params(n2, valuesize, ti, n1, NULL);

If ie->modifiable (the IndexExp appears in left hand side of an assignment
expression), typeid(taa) is set to the 2nd argument of _aaGetY(). But, if taa
is not mutable, it will be a TypeInfo_Const reference that points
TypeInfo_AssociativeArray.

On the other hand, the _aaGetY() function is defined as:

void* _aaGetY(AA* aa, const TypeInfo_AssociativeArray ti, in size_t valuesize,
in void* pkey)
{
    if (aa.impl is null)
    {
        aa.impl = new Impl();
        aa.impl.buckets = aa.impl.binit[];
        aa.impl.firstUsedBucket = aa.impl.buckets.length;
        aa.impl._keyti = cast() ti.key;     // <-----
    }
    return _aaGetImpl(aa, ti.key, valuesize, pkey);
}

And ti does not point an instance of TypeInfo_AssociativeArray, so will cause
segfault at the ti.key access.

--
Jan 24 2015