<table border="1" cellspacing="0" cellpadding="8">
    <tr>
        <th>Issue</th>
        <td>
            <a href=https://github.com/llvm/llvm-project/issues/60349>60349</a>
        </td>
    </tr>

    <tr>
        <th>Summary</th>
        <td>
            `-frandomize-layout-seed` inconsistently randomizes all-function-pointers structs
        </td>
    </tr>

    <tr>
      <th>Labels</th>
      <td>
      </td>
    </tr>

    <tr>
      <th>Assignees</th>
      <td>
      </td>
    </tr>

    <tr>
      <th>Reporter</th>
      <td>
          ebiggers
      </td>
    </tr>
</table>

<pre>
    I found that if the Linux kernel v6.2-rc5 is built with clang (latest git, commit `898b5c9f5e77`) with `CONFIG_RANDSTRUCT=y` included in the kernel configuration, there is a miscompilation in `drivers/gpu/drm/amd/display/dc/dcn303/dcn303_init.c`.

The problem is that when clang's `-frandomize-layout-seed` option automatically randomizes the layout of structs that contain only function pointers, it incorrectly skips structs that contain implicit forward declarations.  For example, consider the following struct:

```
struct foo {
        struct bar *(*f)(void);
        struct bar *(*g)(void);
};
```

If `struct bar` is already declared, then clang sees that `struct foo` contains
only function pointers and it randomizes the layout of `struct foo`.

However, if `struct bar` is not yet declared, then clang inserts an implicit forward declaration of `struct bar` into `struct foo`.  Because of that, clang then incorrectly considers `struct foo` to contain fields other than function pointers, so it doesn't randomize the layout of `struct foo`.

This also can happen with enums:

```
struct foo {
        enum bar (*f)(void);
        enum bar (*g)(void);
};
```

In either case, the real trouble happens when `bar` has an explicit declaration in some translation units but not others.  That makes `struct foo` be randomized in some translation units but not others.

Changing [this line of code in SemaDecl.cpp](https://github.com/llvm/llvm-project/blob/6cfebf39103e6f46dfb3ed50930b81cb674384e5/clang/lib/Sema/SemaDecl.cpp#L18875) to return `true` instead of `false` fixes the bug.
</pre>
<img width="1px" height="1px" alt="" src="http://email.email.llvm.org/o/eJycVl2P2ygU_TXk5SoRwfHXQx5mJspupaortbPPFYaLzRaDBXhmsr9-BfZ8tdPRtlKEicO9nHvO4RIegu4t4pGU16Q8bfgcB-eP2Om-Rx82nZOX4wdQbrYS4sAjaAVxQPio7fwA39BbNHBX7djWixJ0gG7WJsK9jgMIw20PhDWGRwwReh0JuwHhxlFHIBVt2qYrRatKrGtSUcLaJZBU9OavT-cPf3z9fPXp9OX28983t6Q4XUhFQVthZokStM1AVgjCWaX72fOonU27xAE9JkAcRh2EGydt8o8pkFRUen2HPhB27qeZsLP0I2FnPso012Ey_JJmIg-2oMXT5Ku2Ou4EqeiO0BOhV8t4OyBM3nUGx7RtJut-QLvQQFgd0rZb5bmVbtT_4tbwi5vjNiDKVJmbMjw-RzfyqAU35gJPq0OudgkBpyBEP4u47iOcjVxbcNZcQM1W5EyT0zbmGm9Ax8Sc8x5FNBcI3_QU3s6hx8looSMo5--5lyBRGL4QG3YAZ-cBH_g4GVzUtEFL9Bmecsa4e237NTUprl5SlDRePvnrsgaUc0Dq68eF7fq64x4IuyKsIexKEdYS1tw5LdOseH91_5PV9el5_hrKMn5QSaLnjNlvAbjxyOVlJQLlaq9VWQiIK4XPwcq5FLxyGpb0b6sD3Mokz0-V_j7rK9f96e7xDn2W-G301kW4YPwZem0D-phQvKv8ayCP2W10P8IDuEbB54ApJvGSbZI3y_u-9OGje8KP3EX3ZEml0cgALp3plNG-7fHgEo_SYbCE1S8Y_RVCb4eseHAguIWBTxPapSuhncfwW45OkatD3zfzdwt_28cWUGeyBA-4Cg4euYHo3dwZXAsLS4ciFV0VHXh2Aj6sTnjpAG0huBEhem7D2ktnq2Pq-THbLAuUesRtOg0j_4Zv6NrhszDy_yd9Wd_NwG2fugwpr2PSy2ib3SacxJTyC478hMLsxDSR8kRYM8Q4ZfHYObV8HYe52wmXer4xd4-P7eTdPygiYefOuI6wcyUUdqpo97TASh0qqboCZUnbgnbNXnRVfSiaA5aEndc-fzY6BSYI6-MJCSs-7pumLtNFFx14jLPP7Ec_43KgQkQuV5MqbkJ-rfTD2hW6ud9t5LGQbdHyDR73VX1ompbRcjMcK17VUhy4qltZcVbtGywKVXZFV6qCNeVGHxllBd2zhtaU0nLX7ZtGtko1TcNKpipyoDhybXaJjJ3z_UaHMOOxosWh3RjeoQmPfxX8MTPWzX0gB2p0iOE5LOpo8Pj-fZf6gA06RLTx9U3Hjdk-nvDtU59cb6vN7M3xl-XMdaTbPpfyXwAAAP__-9HqCw">