Repository: rust
Issue: No warning for violating AAPCS64
Labels: A-FFI,C-bug,A-layout,O-AArch64

<!--
Thank you for filing a bug report! 🐛 Please provide a short summary of the bug,
along with any information you feel relevant to replicating the bug.
-->

I tried this code with `rustc how-to-violate-an-abi.rs --target=aarch64-unknown-linux-gnu`:

```rust
#[repr(C, packed)]
pub struct PackedC {
    a: u8,
    b: u16,
}

#[no_mangle]
pub extern "C" fn exposed_illegal_struct(c: PackedC) -> PackedC {
    PackedC { a: c.a +1, b: c.b -1 } 
}
```

I expected to see this happen: At least a warning about violating the Procedure Call Standard for the Arm 64-bit Architecture ("AAPCS64").

Instead, this happened: the code passed without rustc erroring (until rustc errored on finding I haven't installed the right linker yet). Concerning. Perhaps I am doing something wrong?

### Meta
<!--
If you're using the stable version of the compiler, you should also check if the
bug also exists in the beta or nightly versions.
-->

`rustc --version --verbose`:
```
rustc 1.57.0-nightly (51e514c0f 2021-09-12)
binary: rustc
commit-hash: 51e514c0fb4f9afcaae3b02dd9ccb93e15b30ef8
commit-date: 2021-09-12
host: x86_64-pc-windows-msvc
release: 1.57.0-nightly
LLVM version: 13.0.0
```

### Details

This came up [during discussion of the Arm ABI and bitfields]( https://github.com/rust-lang/rfcs/pull/3113#discussion_r704875707). In essence, as it was explained to me: `#[repr(C)]` and `#[repr(packed)]` are not really quite compatible since compilers have a lot of liberty to intepret things like `__attribute__((__packed__))`, which is, in any case, a compiler extension and not part of the C standard. As such, Arm actually explicitly disallows them in code that exposes an interface. Here we have some code which could do exactly that: return a type with an ABI-breaking combination of reprs.

To quote Arm (emphasis mine):
> The AAPCS64 does not allow exported interfaces to contain **packed structures** or bit-fields. However a scheme for laying out packed bit-fields can be achieved by reducing the alignment, A, in the above rules to below that of the natural container type. ARMCC uses an alignment of A=8 in these cases, but GCC uses an alignment of A=1.

The varying alignment described here is itself an excellent example as to how `#[repr(packed)]` can be subject to differing interpretations between compilers, and would ideally have a limited amount of exposure to the logic outside a _single_ compiler on any system. Of course, we don't have packed bitfields in Rust yet, but we do have packed structs!

This may fall under the `improper_ctypes` lint, however as it is apparently an explicit ABI violation on this architecture, something a bit more stern than just a warning does seem like it may be appropriate if we detect it "leaking out". It also does seem doubtful we can truly be inter-compiler consistent in cases where the ABI is any less specified than such a quite thorough algorithm. Of course, even on Arm, something like this may be required of a Rust programmer for interacting with legacy code that decides it is "too good" for the AAPCS anyways, though we might need additional hints for producing a proper layout (and ideally a better solution can be found).