Skip to content

Conversation

@bstaletic
Copy link
Collaborator

Description

Even though our cmake uses -fno-strict-aliasing, not all extensions do. Since C++17, we can actually fix -Wstrict-aliasing errors. For now, let's just see how things fail in CI.

Suggested changelog entry:

Copy link
Collaborator Author

@bstaletic bstaletic left a comment

Choose a reason for hiding this comment

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

Comment on lines 165 to 169
#if defined(__has_include) && __has_include(<version>)
# include <version>
#endif
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Since C++20, __cpp_lib_foo feature test macros are in <version> header and at least clang respects that.

Comment on lines 13 to 20
#if defined(__cpp_lib_launder) && !(defined(_MSC_VER) && (_MSC_VER < 1914))
# define PYBIND11_STD_LAUNDER std::launder
# define PYBIND11_HAS_STD_LAUNDER 1
#else
# define PYBIND11_STD_LAUNDER
# define PYBIND11_HAS_STD_LAUNDER 0
#endif

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

This is the best check that @YannickJadoul and I could come up with.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Like I mentioned in the other comment, __cpp_lib_launder will be defined in <version> in C++20. If I define these macros here, I won't get that header from detail/common.h.

Should I include <version> here? Move these macro definitions to common.h?

Also defined(__cpp_lib_launder) should be defined(__cpp_lib_launder) && __cpp_lib_launder >= 201606.

Comment on lines 46 to 48
# if !PYBIND11_HAS_STD_LAUNDER
# pragma GCC diagnostic ignored "-Wstrict-aliasing"
# endif
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

In case we don't have std::launder, we can't tackle -Wstrict-aliasin. At least not easily, without breaking or a major refactoring.

#endif
if (!std::is_trivially_destructible<Func>::value)
rec->free_data = [](function_record *r) { ((capture *) &r->data)->~capture(); };
rec->free_data = [](function_record *r) { PYBIND11_STD_LAUNDER((capture *) &r->data)->~capture(); };
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

As far as I know, this is the only place where we need to launder.

Copy link
Collaborator

@YannickJadoul YannickJadoul left a comment

Choose a reason for hiding this comment

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

I wish there was a way to avoid std::launder (and UB on C++<17), but ... myeah, it's better than before, at least.

Comment on lines 154 to 159
#if defined(__cpp_lib_launder) && !(defined(_MSC_VER) && (_MSC_VER < 1914))
# define PYBIND11_STD_LAUNDER std::launder
# define PYBIND11_HAS_STD_LAUNDER 1
#else
# define PYBIND11_STD_LAUNDER
# define PYBIND11_HAS_STD_LAUNDER 0
Copy link
Collaborator

Choose a reason for hiding this comment

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

Oh, I'd still move this up (underneath detail/common.h) having been included?

#if defined(__GNUG__) && !defined(__clang__) && __GNUC__ >= 6
# pragma GCC diagnostic pop
#endif
#if !PYBIND11_HAS_STD_LAUNDER
Copy link
Collaborator

Choose a reason for hiding this comment

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

Suggested change
#if !PYBIND11_HAS_STD_LAUNDER
#if defined(__GNUG__) && !PYBIND11_HAS_STD_LAUNDER

or

Suggested change
#if !PYBIND11_HAS_STD_LAUNDER
#if defined(__GNUG__) && !defined(__clang__) && !PYBIND11_HAS_STD_LAUNDER

@bstaletic bstaletic force-pushed the strict-aliasing branch 4 times, most recently from e7225e6 to 257af0e Compare January 23, 2021 23:50
@YannickJadoul
Copy link
Collaborator

I was not expecting that to work, but that message seems to have been received...
Well, it's Saturday evening. Let's not judge MSVC for having had one too many?

YannickJadoul added a commit to elkhrt/pybind11 that referenced this pull request Jan 30, 2021
YannickJadoul added a commit to elkhrt/pybind11 that referenced this pull request Jan 30, 2021
YannickJadoul added a commit that referenced this pull request Jan 30, 2021
#2819)

* When determining if a shared_ptr already exists, use a test on the weak_ptr instead of a try/catch block.

* When determining if a shared_ptr already exists, use a test on the weak_ptr instead of a try/catch block.

* weak_from_this is only available in C++17 and later

* Switch to use feature flag instead of C++ version flag.

* Add Microsoft-specific check.

* Avoid undefined preprocessor macro warning treated as error.

* Simplify shared_from_this in init_holder

* Include <version> in detail/common.h (~stolen~ borrowed from @bstaletic's #2816)

* Move class_::get_shared_from_this to detail::try_get_shared_from_this

* Simplify try_get_shared_from_this by using weak_ptr::lock()

Co-authored-by: Yannick Jadoul <[email protected]>
@bstaletic
Copy link
Collaborator Author

I think I got this to work on icc as well.

Copy link
Collaborator

@henryiii henryiii left a comment

Choose a reason for hiding this comment

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

Always happy to see these ignores go away (even if only conditionally)! And become more specific to the code they are there for.

I'm wondering if things like missing-field-initializers can go away after the last few PRs fixing clang-tidy?

@Skylion007
Copy link
Collaborator

Always happy to see these ignores go away (even if only conditionally)! And become more specific to the code they are there for.

I'm wondering if things like missing-field-initializers can go away after the last few PRs fixing clang-tidy?

Not quite, I can enable that clang-tidy check too.

@bstaletic
Copy link
Collaborator Author

I'm wondering if things like missing-field-initializers can go away after the last few PRs fixing clang-tidy?

I tried and gcc 11 did not complain. However, this is surprising:

In function ‘cast’,
    inlined from ‘operator()’ at /home/bstaletic/work/pybind11/include/pybind11/pybind11.h:213:43,
    inlined from ‘_FUN’ at /home/bstaletic/work/pybind11/include/pybind11/pybind11.h:191:21:
/home/bstaletic/work/pybind11/include/pybind11/cast.h:567:13: warning: ‘operator delete’ called on unallocated object ‘int_string_pair’ [-Wfree-nonheap-object]
  567 |             delete src;
      |             ^
/home/bstaletic/work/pybind11/include/pybind11/cast.h: In function ‘_FUN’:
/home/bstaletic/work/pybind11/tests/test_builtin_casters.cpp:174:40: note: declared here
  174 |     static std::pair<int, std::string> int_string_pair{2, "items"};
      |                                        ^
In function ‘cast’,
    inlined from ‘operator()’ at /home/bstaletic/work/pybind11/include/pybind11/pybind11.h:213:43,
    inlined from ‘_FUN’ at /home/bstaletic/work/pybind11/include/pybind11/pybind11.h:191:21:
/home/bstaletic/work/pybind11/include/pybind11/stl.h:186:5: warning: ‘operator delete’ called on unallocated object ‘lvv’ [-Wfree-nonheap-object]
  186 |     PYBIND11_TYPE_CASTER(Type, _("List[") + value_conv::name + _("]"));
      |     ^
/home/bstaletic/work/pybind11/include/pybind11/stl.h: In function ‘_FUN’:
/home/bstaletic/work/pybind11/tests/test_stl.cpp:79:38: note: declared here
   79 |     static std::vector<RValueCaster> lvv{2};
      |                                      ^

Copy link
Collaborator

@rwgk rwgk left a comment

Choose a reason for hiding this comment

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

The pragma block at the top of pybind11.h is evil (I lost a few hours already because of this), nice to see at least one item go.

Side remark: The repetition of a complex #if for the pragma ... pop seems unfortunate (DRY) but is common practice. Might be nice to go through at some point to do something like this:

#if something complicated
#  pragma ...
#  define PYBIND11_PRAGMA_ACTIVE 1
#endif
...
#if defined(PYBIND11_PRAGMA_ACTIVE)
#  pragma ...
#  undef PYBIND11_PRAGMA_ACTIVE
#endif 

@rwgk
Copy link
Collaborator

rwgk commented Jul 15, 2021

I'm wondering if things like missing-field-initializers can go away after the last few PRs fixing clang-tidy?

I tried and gcc 11 did not complain. However, this is surprising:

None of our sanitizers picks up on this. I think they would if it was real.

@Skylion007 Skylion007 merged commit 5cd3750 into pybind:master Jul 15, 2021
@github-actions github-actions bot added the needs changelog Possibly needs a changelog entry label Jul 15, 2021
@henryiii henryiii removed the needs changelog Possibly needs a changelog entry label Jul 15, 2021
@bstaletic bstaletic deleted the strict-aliasing branch July 16, 2021 10:13
rwgk added a commit to rwgk/pybind11 that referenced this pull request Mar 31, 2025
…andard_layout`)

https://chatgpt.com/share/67ea07fa-9afc-8008-95af-4d7e0829a9c2

Apply std::launder consistently to functional capture storage

This commit improves the robustness and clarity of pybind11's internal
capture mechanism for bound C++ callables stored in function_record.

- Introduces `capture::from_data(void**)` to encapsulate reinterpretation
  of the in-place `capture` object stored in `rec->data`, ensuring
  consistent use of `std::launder`.
- Adds a `static_assert` that verifies `capture` is standard layout,
  making explicit the precondition necessary for these low-level
  performance optimizations.
- Centralizes the `PYBIND11_STD_LAUNDER` and `PYBIND11_HAS_STD_LAUNDER`
  macros into `common.h` to enable reuse across headers.
- Replaces ad hoc laundering and strict aliasing warnings with a more
  principled and maintainable approach.

This refines and generalizes the use of `std::launder` introduced in
PR pybind#2816 (2021-07-15), addressing undefined behavior more thoroughly
while preserving ABI and performance characteristics.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants