[llvm] [ADT] Fix alignment check in unique_function constructor (PR #99403)
Dmitry Yanovsky via llvm-commits
llvm-commits at lists.llvm.org
Wed Jul 17 16:23:34 PDT 2024
https://github.com/kerambyte created https://github.com/llvm/llvm-project/pull/99403
Right now the check fails for any state-capturing lambda since this expression - `alignof(decltype(StorageUnion.InlineStorage))` - returns 1 for the alignment value and not 4/8 as expected ([MSVC|Clang|GCC](https://godbolt.org/z/eTEdq4xjM)). So this check fails for pretty much any state-capturing callable we try to store into a `unique_function` and we take the out-of-line storage path:
```
if (sizeof(CallableT) > InlineStorageSize ||
alignof(CallableT) > alignof(decltype(StorageUnion.InlineStorage))) {
// ...
}
```
The fix is simply to use an explicit const variable to store the alignment value.
There is no easy way to unit-test the fix since inline storage is considered to be an implementation detail so we shouldn't assume how the lambda ends up being stored.
>From 9506c5f340b3ac49477a7a61684def1ecf6e57c2 Mon Sep 17 00:00:00 2001
From: kerambyte <kerambyte at gmail.com>
Date: Thu, 18 Jul 2024 00:14:54 +0100
Subject: [PATCH] initial commit
---
llvm/include/llvm/ADT/FunctionExtras.h | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/llvm/include/llvm/ADT/FunctionExtras.h b/llvm/include/llvm/ADT/FunctionExtras.h
index 49e0e8ab0db40..ad5c89cbc8bda 100644
--- a/llvm/include/llvm/ADT/FunctionExtras.h
+++ b/llvm/include/llvm/ADT/FunctionExtras.h
@@ -80,6 +80,7 @@ using EnableIfCallable = std::enable_if_t<std::disjunction<
template <typename ReturnT, typename... ParamTs> class UniqueFunctionBase {
protected:
static constexpr size_t InlineStorageSize = sizeof(void *) * 3;
+ static constexpr size_t InlineStorageAlign = alignof(void *);
template <typename T, class = void>
struct IsSizeLessThanThresholdT : std::false_type {};
@@ -161,7 +162,8 @@ template <typename ReturnT, typename... ParamTs> class UniqueFunctionBase {
// provide three pointers worth of storage here.
// This is mutable as an inlined `const unique_function<void() const>` may
// still modify its own mutable members.
- alignas(void *) mutable std::byte InlineStorage[InlineStorageSize];
+ alignas(InlineStorageAlign) mutable std::byte
+ InlineStorage[InlineStorageSize];
} StorageUnion;
// A compressed pointer to either our dispatching callback or our table of
@@ -262,7 +264,7 @@ template <typename ReturnT, typename... ParamTs> class UniqueFunctionBase {
bool IsInlineStorage = true;
void *CallableAddr = getInlineStorage();
if (sizeof(CallableT) > InlineStorageSize ||
- alignof(CallableT) > alignof(decltype(StorageUnion.InlineStorage))) {
+ alignof(CallableT) > InlineStorageAlign) {
IsInlineStorage = false;
// Allocate out-of-line storage. FIXME: Use an explicit alignment
// parameter in C++17 mode.
More information about the llvm-commits
mailing list