https://gcc.gnu.org/bugzilla/show_bug.cgi?id=71224

            Bug ID: 71224
           Summary: Looping over local copy of aggregate invokes undefined
                    behavior -Waggressive-loop-optimizations
           Product: gcc
           Version: 7.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: middle-end
          Assignee: unassigned at gcc dot gnu.org
          Reporter: ibuclaw at gdcproject dot org
  Target Milestone: ---

This probably is related to PR71177 and PR57199, but unlike them, this test
case doesn't have any external header dependencies, and also affects gcc as
well as g++.

However though it was in my D frontend that I first noticed this problem.

---
typedef __SIZE_TYPE__ size_t;

typedef struct Array
{
    size_t length;
    size_t* ptr;
} Array;

void setlength(Array* pthis, size_t nlength)
{
    Array aggr = {
        .length=pthis->length - nlength,
        .ptr=pthis->ptr + nlength
    };

    for (size_t key = 0; key < aggr.length; key++)
        aggr.ptr[key] = 1;
}

void insertBack(Array* pthis)
{
    setlength(pthis, pthis->length + 1);
}
---

Can even reproduce if I were to lower the loop in the same way that g++ does.

---
void setlength(Array* pthis, size_t nlength)
{
    Array aggr = {.length=pthis->length - nlength, .ptr=pthis->ptr + nlength};
    size_t key = 0;

    while (1)
    {
        if (aggr.length <= key)
            break;
        aggr.ptr[key] = 1;
        key++;
    }
}
---


Just like in PR57199, if I were to add the following inside the for body.
---
        if (__builtin_expect(aggr.length > key, 0))
            __builtin_unreachable();
---

Then the warning goes away.

Reply via email to