<html>
    <head>
      <base href="http://llvm.org/bugs/" />
    </head>
    <body><table border="1" cellspacing="0" cellpadding="8">
        <tr>
          <th>Bug ID</th>
          <td><a class="bz_bug_link 
          bz_status_NEW "
   title="NEW --- - Assertion failed in CGRecordLayoutBuilder.cpp:526 (Prior->Kind == MemberInfo::Field && !Prior->FD && "Only storage fields have tail padding!)"
   href="http://llvm.org/bugs/show_bug.cgi?id=21040">21040</a>
          </td>
        </tr>

        <tr>
          <th>Summary</th>
          <td>Assertion failed in CGRecordLayoutBuilder.cpp:526 (Prior->Kind == MemberInfo::Field && !Prior->FD && "Only storage fields have tail padding!)
          </td>
        </tr>

        <tr>
          <th>Product</th>
          <td>clang
          </td>
        </tr>

        <tr>
          <th>Version</th>
          <td>trunk
          </td>
        </tr>

        <tr>
          <th>Hardware</th>
          <td>PC
          </td>
        </tr>

        <tr>
          <th>OS</th>
          <td>Windows NT
          </td>
        </tr>

        <tr>
          <th>Status</th>
          <td>NEW
          </td>
        </tr>

        <tr>
          <th>Severity</th>
          <td>normal
          </td>
        </tr>

        <tr>
          <th>Priority</th>
          <td>P
          </td>
        </tr>

        <tr>
          <th>Component</th>
          <td>C++
          </td>
        </tr>

        <tr>
          <th>Assignee</th>
          <td>unassignedclangbugs@nondot.org
          </td>
        </tr>

        <tr>
          <th>Reporter</th>
          <td>andrea.dibiagio@gmail.com
          </td>
        </tr>

        <tr>
          <th>CC</th>
          <td>dgregor@apple.com, llvmbugs@cs.uiuc.edu
          </td>
        </tr>

        <tr>
          <th>Classification</th>
          <td>Unclassified
          </td>
        </tr></table>
      <p>
        <div>
        <pre>To reproduce the assertion failure,

//////
struct A {
  int a0[0];   // zero-length array.
};

struct B : private A {  // assertion failure!
  int b;
};

B bb;
//////


CGrecordLayoutBuilder.cpp:526: void
{anonymous}::CGRecordLowering::clipTailPadding(): Assertion `Prior->Kind ==
MemberInfo::Field && !Prior->FD && "Only storage fields have tail padding!"
failed.

Note that if we replace the zero-length array within struct A with a C99-style
flexible array, then the compiler doesn't assert. Instead, it emits the
following " error: base class 'A' has a flexible array member'.

Example:

//////
struct A {
  int a0[];  // c99 style flexible array.
};

struct B : private A {  // expected diagnostic error.
  int b;
};

B bb;
//////

The error is raised by Sema (see SemaDeclCXX.cpp at around line 1457). The
comments in the code say that: "A class which contains a flexible array member
is not suitable for use as a base class". The motivation in this case is: "if
the layout determines that a base comes before the derived class, the flexible
array member would index into the derived class".

My opinion is that we should treat zero-length arrays the same way as flexible
arrays for the purpose of layout. This is because zero-length arrays are an
alternative (deprecated) way to specify flexible arrays (see
<a href="https://gcc.gnu.org/onlinedocs/gcc/Zero-Length.html">https://gcc.gnu.org/onlinedocs/gcc/Zero-Length.html</a> for further details).
At the very least, clang shouldn't assert.</pre>
        </div>
      </p>
      <hr>
      <span>You are receiving this mail because:</span>
      
      <ul>
          <li>You are on the CC list for the bug.</li>
      </ul>
    </body>
</html>