clang::CompoundLiteral::getInitializer() should use cast_or_null() (or I am missing something)

dear list,

I am working with .c files that uses the GNU extensions, in particular
the diag::ext_gnu_empty_initializer related extension.

Unfortunately this means the Stmt* Init of the class may be zero.

When it is the case getInitializer() crashes because cast() is not meant
to be used on null pointers.

It really seems a bug, but I am not posting a bug report because I read
in the class body this intriguing comment:
    // FIXME: Init should never be null.

What is the story then? How emtpy initializer finish in the AST?

Thanks,
pb

hi Paolo,

Please include an example, it would be very useful to understand the details of what you're talking about,

-Chris

I attached an extract of the file that gives me problems.

It is a function from gcc.c downloadable from
http://people.csail.mit.edu/smcc/projects/single-file-programs/

I just added some meaningless definitions of structures and variables so
the file does compile with:
$ gcc -c -std=gnu89 -w

This instead is an extract of clang driver ast dump:
'''
(BinaryOperator 0x18c4cc0 <col:14, col:67> 'unsigned long' '+'
  (ImplicitCastExpr 0x18c4c80 <col:14, col:16> 'unsigned long'
    (ParenExpr 0x18c4ac0 <col:14, col:16> 'size_t':'unsigned int'
      (DeclRefExpr 0x18c4a80 <col:15> 'size_t':'unsigned int' Var='s'
0x18c4700))) (ParenExpr 0x18c4c40 <col:20, col:67> 'unsigned long'
    (ParenExpr 0x18c4c00 <col:21, col:66> 'unsigned long'
      (UnaryOperator 0x18c4bc0 <col:22, col:64> 'unsigned long' prefix
'__builtin_offsetof' (MemberExpr 0x18c4b80 <:0:0, gcc_extract.c:61:64>
'int' .u 0x18b1bd0 (CompoundLiteralExpr 0x18c4b00 <:0:0> 'struct
max_alignment' <<<NULL>>>))))))
'''

I think the <<<NULL>>> in compound literal expression is problem.
this little member function of a statement visitor crashes:
'''
void Visitor::VisitCompoundLiteralExpr(clang::CompoundLiteralExpr *node) {
    std::cout << "CompoundLiteral\n";
// if (node-> hasInitializer()) {
       std::cout << "hasInitializer\n";
       clang::Expr* init = node-> getInitializer();
       Visit(init);
// }
// else {
// std::cout << "no initializer\n";
// }
}
'''
The commented part is a test of mine, I tried adding a member to
clang::CompoundLiteralExpr:

bool hasInitializer() const { return Init != 0; }

and with this slight modification it seems working fine.

Re-reading better it does not seem ext_gnu_empty_initializer related, it
seem more __builtin_offsetof related, sorry for the confusion.

Thanks,
pb

gcc_extract.c (2.37 KB)