Dynamic Zero-Length Arrays in C++ : <pre><code>#include &lt;stdlib.h&gt;

void *operator new[](size_t size, int n){
    if( size != 0 &amp;&amp; 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;
}
</code></pre>

<p>This code (<a href="https://godbolt.org/g/hjo7Xn" rel="noreferrer">https://godbolt.org/g/hjo7Xn</a>) 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. </p>

<p>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 <em>new-expression</em>, that is, the one with <em>new-type-id</em> and without parentheses (Case 1). </p>

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

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

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

<p>The wording <code>(if any)</code> 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 <em>new-type-id</em> and without parentheses (Case 1).</p>

<p>Thanks in advance.</p>

<p>Notes:</p>

<ol>
<li>ISO/IEC 14882:2003, Section 8.3.4, Paragraph 1: 

<blockquote>
  <p>If the <em>constant-expression</em> (5.19) is present, it shall be an integral constant expression and its value shall be greater than zero.</p>
</blockquote></li>
<li>ISO/IEC 14882:2003, Section 5.3.4, Paragraph 6: 

<blockquote>
  <p>The <em>expression</em> in a <em>direct-new-declarator</em> shall have integral or enumeration type (3.9.1) with a non-negative value.</p>
</blockquote></li>
<li>ISO/IEC 14882:2003, Section 5.3.4, Paragraph 7: 

<blockquote>
  <p>When the value of the <em>expression</em> in a <em>direct-new-declarator</em> is zero, the allocation function is called to allocate an array with no elements.</p>
</blockquote></li>
<li>ISO/IEC 14882:2003, Section 5.3.4, Paragraph 1:

<blockquote>
  <p><em>new-expression</em>:</p>
  
  <p>::<code>opt</code> <strong>new</strong> <em>new-placement</em><code>opt</code> <em>new-type-id</em> <em>new-initializer</em><code>opt</code></p>
  
  <p>::<code>opt</code> <strong>new</strong> <em>new-placement</em><code>opt</code> ( <em>type-id</em> ) <em>new-initializer</em><code>opt</code></p>
</blockquote></li>
<li>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).</li>
<li>Interesting Herb Sutter's <a href="https://herbsutter.com/2009/09/02/when-is-a-zero-length-array-okay/" rel="noreferrer">post</a> about zero-length arrays.</li>
<li>The code in the example is a slightly modified test from <a href="https://www.solidsands.nl" rel="noreferrer">SolidSands'</a> SuperTest suite.</li>
</ol>
