llvm / llvm/llvm-project

[Clang] `APPLE` specific ABI Issue with Reuse of Tail Padding

Open
#175,486 3 comments 0 reactions 0 assignees View on GitHub
ABI clang platform:macos
Dominant language
LLVM
Stars
40.5k
Forks
18.7k
PR merge metrics
PR metrics pending

Description

This may act as a follow-up on [Bug 16537 - ABI issue with the C++11 definition of POD and tail padding](https://bugs.llvm.org/show_bug.cgi?id=16537), but it is currently reproducible on `homebrew/clang` (`apple-clang` should also have the same issue). Below I have attached the test case:
```cpp
// Compiled with clang++ --std=c++23
#include

typedef unsigned long long int64;
typedef unsigned char int8;

// non-POD in 03
struct pod_in_11_only {
private:
int64 x;
};

// non-POD in 03
struct tail_padded_pod_in_11_only {
pod_in_11_only pod11;
int8 tail_padding;
};

struct might_use_tail_padding : public tail_padded_pod_in_11_only {
int8 may_go_into_tail_padding;
};

int main() {
printf("sizeof(might_use_tail_padding) == %lu\n", sizeof(might_use_tail_padding));
printf("%s\n", sizeof(might_use_tail_padding) == 16 ? "Using tail padding"
: "NOT using tail padding");
return 0;
}
```
This case as of now, on **Homebrew clang version 21.1.8** still does not reuse the tail padding, which is at odds with the [Itanium C++ ABI](https://itanium-cxx-abi.github.io/cxx-abi/abi.html#POD).
> There have been multiple published revisions to the ISO C++ standard, and each one has included a different definition of POD. To ensure interoperation of code compiled according to different revisions of the standard, it is necessary to settle on a single definition for a platform. A platform vendor may choose to follow a different revision of the standard, but by default, the definition of POD under this ABI is the definition from the 2003 revision (TC1).

The difference seems to stem from the difference of POD definition used when determining the layout. After tweaking the test case so that it is no longer a POD by the C++11 definition, this reuses the tail-padding as expected.
```cpp
// Compiled with clang++ --std=c++23

#include

typedef unsigned long long int64;
typedef unsigned char int8;

// non-POD in 11
struct non_pod_in_11 {
~non_pod_in_11() {}
private:
int64 x;
};

// non-POD in 11
struct tail_padded_non_pod_in_11 {
non_pod_in_11 pod11;
int8 tail_padding;
};

struct might_use_tail_padding : public tail_padded_non_pod_in_11 {
int8 may_go_into_tail_padding;
};

int main() {
printf("sizeof(might_use_tail_padding) == %lu\n", sizeof(might_use_tail_padding));
printf("%s\n", sizeof(might_use_tail_padding) == 16 ? "Using tail padding"
: "NOT using tail padding");
return 0;
}
```
I suspect this is also why the behaviour of the following code differs (does not reuse tail padding on `homebrew/clang`):
```cpp
// Compiled with clang++ --std=c++23
struct AllowOverlapMixin {};

struct Foo: AllowOverlapMixin {
long long foo_val;
bool foo_val2;
};

template
struct MaybeDeleted {
[[no_unique_address]] T val;
bool deleted;
};

static_assert(sizeof(Foo) == 16);
static_assert(alignof(Foo) == 8);
static_assert(sizeof(MaybeDeleted) == 16); // 24 on homebrew/clang, does not compile
```

Here are the details of the running environment if needed.
```
$ clang++ --version
Homebrew clang version 21.1.8
Target: arm64-apple-darwin22.4.0
Thread model: posix
InstalledDir: /opt/homebrew/Cellar/llvm/21.1.8/bin
Configuration file: /opt/homebrew/etc/clang/arm64-apple-darwin22.cfg

$ sysctl -n machdep.cpu.brand_string
Apple M1 Pro
```

Contributor guide

Open the contributing guide

Research direction

Start by reproducing the attached C++ cases with clang++ --std=c++23 on the reported Apple target, including the sizeof and static_assert checks. Read the Itanium C++ ABI tail-padding and POD rules alongside Clang's record-layout and ABI handling. Done means the Apple-specific layouts are resolved consistently with the intended ABI behavior, with regression coverage for the reproductions.

Written by the indexing model from the issue text.

Assessment

Tech stack
cpp
Domain
compilers
Issue type
Bug
Difficulty
5/5
Estimated time
Over a week
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.