Skip to content

[libc++] Fix padding calculation for function reference types #142125

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jun 3, 2025

Conversation

frederick-vs-ja
Copy link
Contributor

#109028 caused sizeof to be sometimes applied to function reference types, which makes a program ill-formed. This PR handles reference types by specializations to prevent such bogus sizeof expression to be instantiated.

Fixes #142118.

@frederick-vs-ja frederick-vs-ja requested a review from a team as a code owner May 30, 2025 11:21
@llvmbot llvmbot added the libc++ libc++ C++ Standard Library. Not GNU libstdc++. Not libc++abi. label May 30, 2025
@llvmbot
Copy link
Member

llvmbot commented May 30, 2025

@llvm/pr-subscribers-libcxx

Author: A. Jiang (frederick-vs-ja)

Changes

#109028 caused sizeof to be sometimes applied to function reference types, which makes a program ill-formed. This PR handles reference types by specializations to prevent such bogus sizeof expression to be instantiated.

Fixes #142118.


Full diff: https://github.com/llvm/llvm-project/pull/142125.diff

2 Files Affected:

  • (modified) libcxx/include/__memory/compressed_pair.h (+11-4)
  • (modified) libcxx/test/std/utilities/smartptr/unique.ptr/unique.ptr.class/unique.ptr.ctor/pointer_deleter.pass.cpp (+19)
diff --git a/libcxx/include/__memory/compressed_pair.h b/libcxx/include/__memory/compressed_pair.h
index 38798a21fa3c9..fb7b7b7afcc8c 100644
--- a/libcxx/include/__memory/compressed_pair.h
+++ b/libcxx/include/__memory/compressed_pair.h
@@ -15,7 +15,6 @@
 #include <__type_traits/datasizeof.h>
 #include <__type_traits/is_empty.h>
 #include <__type_traits/is_final.h>
-#include <__type_traits/is_reference.h>
 
 #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
 #  pragma GCC system_header
@@ -63,9 +62,17 @@ inline const size_t __compressed_pair_alignment = _LIBCPP_ALIGNOF(_Tp);
 template <class _Tp>
 inline const size_t __compressed_pair_alignment<_Tp&> = _LIBCPP_ALIGNOF(void*);
 
-template <class _ToPad,
-          bool _Empty = ((is_empty<_ToPad>::value && !__libcpp_is_final<_ToPad>::value) ||
-                         is_reference<_ToPad>::value || sizeof(_ToPad) == __datasizeof_v<_ToPad>)>
+template <class _ToPad>
+inline const bool __is_reference_or_unpadded_object =
+    (is_empty<_ToPad>::value && !__libcpp_is_final<_ToPad>::value) || sizeof(_ToPad) == __datasizeof_v<_ToPad>;
+
+template <class _Tp>
+inline const bool __is_reference_or_unpadded_object<_Tp&> = true;
+
+template <class _Tp>
+inline const bool __is_reference_or_unpadded_object<_Tp&&> = true;
+
+template <class _ToPad, bool _Empty = __is_reference_or_unpadded_object<_ToPad> >
 class __compressed_pair_padding {
   char __padding_[sizeof(_ToPad) - __datasizeof_v<_ToPad>] = {};
 };
diff --git a/libcxx/test/std/utilities/smartptr/unique.ptr/unique.ptr.class/unique.ptr.ctor/pointer_deleter.pass.cpp b/libcxx/test/std/utilities/smartptr/unique.ptr/unique.ptr.class/unique.ptr.ctor/pointer_deleter.pass.cpp
index a91abc856fb19..a438bfb58ce44 100644
--- a/libcxx/test/std/utilities/smartptr/unique.ptr/unique.ptr.class/unique.ptr.ctor/pointer_deleter.pass.cpp
+++ b/libcxx/test/std/utilities/smartptr/unique.ptr/unique.ptr.class/unique.ptr.ctor/pointer_deleter.pass.cpp
@@ -32,6 +32,8 @@ bool my_free_called = false;
 
 void my_free(void*) { my_free_called = true; }
 
+TEST_CONSTEXPR_CXX23 void deleter_function(A*) {}
+
 #if TEST_STD_VER >= 11
 struct DeleterBase {
   TEST_CONSTEXPR_CXX23 void operator()(void*) const {}
@@ -325,6 +327,21 @@ TEST_CONSTEXPR_CXX23 void test_nullptr() {
 #endif
 }
 
+template <bool IsArray>
+TEST_CONSTEXPR_CXX23 void test_function_reference() {
+  typedef typename std::conditional<!IsArray, A, A[]>::type VT;
+  {
+    std::unique_ptr<VT, void (&)(A*)> u(nullptr, deleter_function);
+    assert(u.get() == nullptr);
+    assert(u.get_deleter() == deleter_function);
+  }
+  {
+    std::unique_ptr<VT, void (&)(A*)> u(nullptr, deleter_function);
+    assert(u.get() == nullptr);
+    assert(u.get_deleter() == deleter_function);
+  }
+}
+
 TEST_CONSTEXPR_CXX23 bool test() {
   {
     test_basic</*IsArray*/ false>();
@@ -332,6 +349,7 @@ TEST_CONSTEXPR_CXX23 bool test() {
     test_basic_single();
     test_sfinae<false>();
     test_noexcept<false>();
+    test_function_reference<false>();
   }
   {
     test_basic</*IsArray*/ true>();
@@ -339,6 +357,7 @@ TEST_CONSTEXPR_CXX23 bool test() {
     test_sfinae<true>();
     test_sfinae_runtime();
     test_noexcept<true>();
+    test_function_reference<true>();
   }
 
   return true;

template <class _ToPad,
bool _Empty = ((is_empty<_ToPad>::value && !__libcpp_is_final<_ToPad>::value) ||
is_reference<_ToPad>::value || sizeof(_ToPad) == __datasizeof_v<_ToPad>)>
template <class _ToPad>
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do this have to be updated as well?

template <class _ToPad> class __compressed_pair_padding {
char __padding_[((is_empty<_ToPad>::value &&
!__lldb_is_final<_ToPad>::value) ||
is_reference<_ToPad>::value)
? 0
: sizeof(_ToPad) - __datasizeof_v<_ToPad>];
};

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like that changes in lldbsuite should belong to another PR. I've opened #142516.

@ldionne ldionne merged commit 769c42f into llvm:main Jun 3, 2025
185 of 191 checks passed
@frederick-vs-ja frederick-vs-ja deleted the unique_ptr-function-ref branch June 4, 2025 05:50
rorth pushed a commit to rorth/llvm-project that referenced this pull request Jun 11, 2025
…42125)

llvm#109028 caused `sizeof` to be sometimes applied to function reference
types, which makes a program ill-formed. This PR handles reference types
by specializations to prevent such bogus `sizeof` expression to be
instantiated.

Fixes llvm#142118.
DhruvSrivastavaX pushed a commit to DhruvSrivastavaX/lldb-for-aix that referenced this pull request Jun 12, 2025
…42125)

llvm#109028 caused `sizeof` to be sometimes applied to function reference
types, which makes a program ill-formed. This PR handles reference types
by specializations to prevent such bogus `sizeof` expression to be
instantiated.

Fixes llvm#142118.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
libc++ libc++ C++ Standard Library. Not GNU libstdc++. Not libc++abi.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

error: invalid application of 'sizeof' to a function type; with clang++/llvm-20.1.5
4 participants