lundi 30 avril 2018

Dynamic Zero-Length Arrays in C++

#include <stdlib.h>

void *operator new[](size_t size, int n){
    if( size != 0 && n != 0 )
        return calloc(n, size);
    return calloc(1, 1);
}

int main(){

    int * p1;
    const int i = 0;

//  p1 = new (20)  int[i] ; // Case 1 (OK)
    p1 = new (20) (int[i]); // Case 2 (Warning)

    if( p1 == 0 )
        return 1;
    return 0;
}

This code (https://godbolt.org/g/hjo7Xn) compiles successfully with Clang 6.0.0, however, GCC 7.3 issues a warning saying that zero-length arrays are forbidden in C++. If the parentheses are removed (Case 1), the warning goes away.

Unlike statically allocated zero-length arrays (C++03:8.3.4/1), dynamically allocated zero-length arrays are allowed (C++03:5.3.4/6). Nevertheless, in the C++ Standard the latter are explicitly allowed only when following one of the two possible syntax paths of the new-expression, that is, the one with new-type-id and without parentheses (Case 1).

Is it allowed by the C++ Standard to use the new-expression with a zero-length array following the second syntax path, that is, with type-id and parentheses (Case 2)?

The only related quote is C++03:5.3.4/5:

When the allocated object is an array (that is, the direct-new-declarator syntax is used or the new-type-id or type-id denotes an array type), the new-expression yields a pointer to the initial element (if any) of the array.

The wording (if any) would allow an array with no elements, however, it does not seem clear if it refers to both cases or only to the one with new-type-id and without parentheses (Case 1).

Thanks in advance.

Notes:

  1. ISO/IEC 14882:2003, Section 8.3.4, Paragraph 1:

    If the constant-expression (5.19) is present, it shall be an integral constant expression and its value shall be greater than zero.

  2. ISO/IEC 14882:2003, Section 5.3.4, Paragraph 6:

    The expression in a direct-new-declarator shall have integral or enumeration type (3.9.1) with a non-negative value.

  3. ISO/IEC 14882:2003, Section 5.3.4, Paragraph 7:

    When the value of the expression in a direct-new-declarator is zero, the allocation function is called to allocate an array with no elements.

  4. ISO/IEC 14882:2003, Section 5.3.4, Paragraph 1:

    new-expression:

    ::opt new new-placementopt new-type-id new-initializeropt

    ::opt new new-placementopt ( type-id ) new-initializeropt

  5. Although the above quotes are from the C++03 Standard, to the best of my knowledge this issue is still unclear in newer versions of the C++ Standard (C++11, C++14 and C++17).
  6. Interesting Herb Sutter's post about zero-length arrays.
  7. The code in the example is a slightly modified test from SolidSands' SuperTest suite.

Aucun commentaire:

Enregistrer un commentaire