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

            Bug ID: 99471
           Summary: Allow conversion from array of unknown bound to actual
                    known bound
           Product: gcc
           Version: 11.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: c++
          Assignee: unassigned at gcc dot gnu.org
          Reporter: wjwray at gmail dot com
  Target Milestone: ---

P0388 "Permit conversions to arrays of unknown bound" in C++20
does not explicitly discuss conversion back from unknown bound
to the actual bound of the referenced object.

Discussion with Richard Smith suggests that it is (or should be)
allowed to static_cast back to the known bound:

    int a[4]{1,2,3,4};
    int (&r)[] = a;  // P0388 conversion
    int (&b)[4] = r; // error: cannot bind reference of type
                     //        'int (&)[4]' to 'int []'

It is intended that this be allowed (c.f. also bug 93191 end discussion).
However, it requires the compiler to trace the reference back to its object.

Allowing this enables new non-templated array-accepting function apis:
https://godbolt.org/z/1x4Tzs

    constexpr              // marking constexpr gives better codegen
    int sum(int(&x)[])     // despite being not constant evaluated
    {
        auto& in = (int(&)[__builtin_object_size(x,0) / sizeof(int)])x;

        int acc = 0;
        for (int i : in)
            acc += i;
        return acc;
    }

    int main() {
        int a[]{1,2,3,4};
        return sum(a);    // returns 10 (1+2+3+4)
    }

Here, __builtin_object_size requires optimization flags of -O1 or greater
in order to chase back the referenced object and extract its size in bytes.
However, it is not constant evaluated so the C-style cast is casting to VLA.
If the size can indeed be extracted as an integral constant expression then
the cast is a static_cast, or implicit conversion, as above.

So, this 'bug' is two requests:

1. Allow static_cast from T(&)[] -> T(&)[N] where N is the actual size
   (or pointer T(*)[] -> T(*)[N])

2. Provide a constant-evaluated builtin to extract the referenced object size
   (strengthen __builtin_object_size if possible)

(Some sort of array_size builtin, as discussed for C, would be good here too.)

Reply via email to