Michael137 wrote:

> This change leads to a crash in `ConstStructBuilder::Build()` for the 
> following program:
> 
> ```
> struct S {
> };
> 
> union U {
>     struct S s;
>     int x;
> };
> 
> void foo() {
>     union U bar = {};
> }
> ```
> 
> `isEmptyRecordForLayout` returns false for `union U` because the recursive 
> call for `U::x` returns false. This means we call `Init->HasSideEffects()` 
> despite `Init` being null (because `ILE->getNumInits()` is `0`).

Thanks for reporting. It looks like this is only happening when compiling with 
`C`. A slightly more condensed reproducer:
```
union U {
    struct S {} s;
};

void foo() {
    // union U bar = {{}}; // WORKS
    union U bar = {}; // CRASHES
}
```

Looks like when the brace initializer is empty, in C, `ILE->getNumInits()` 
returns `0` (not entirely sure off the top why this is the case). Previously, 
`isZeroSize` would never have been true for fields in C, so this wasn't an 
issue. Now we do hit this code-path and blindly dereference a null `Init`. I 
think we can probably just add a nullptr check here: 
https://github.com/llvm/llvm-project/blob/38752ffd417103621232e6ba6ba70e970e0d6356/clang/lib/CodeGen/CGExprConstant.cpp#L741

Though would like to understand the C vs. C++ significance here first.

https://github.com/llvm/llvm-project/pull/96422
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to