Skip to content

Enable -Wstrict-aliasing warning - #2816

Merged
Skylion007 merged 4 commits into
pybind:masterfrom
bstaletic:strict-aliasing
Jul 15, 2021
Merged

Enable -Wstrict-aliasing warning#2816
Skylion007 merged 4 commits into
pybind:masterfrom
bstaletic:strict-aliasing

Conversation

@bstaletic

Copy link
Copy Markdown
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:

@bstaleticbstaletic left a comment

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

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

Comment threadinclude/pybind11/detail/common.h Outdated
Comment on lines +165 to +169
#if defined(__has_include) && __has_include(<version>)
# include <version>
#endif

Copy link
Copy Markdown
CollaboratorAuthor

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 threadinclude/pybind11/pybind11.h Outdated
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
Copy Markdown
CollaboratorAuthor

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
Copy Markdown
CollaboratorAuthor

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 threadinclude/pybind11/pybind11.h Outdated
Comment on lines +46 to +48
# if !PYBIND11_HAS_STD_LAUNDER
# pragma GCC diagnostic ignored "-Wstrict-aliasing"
# endif

Copy link
Copy Markdown
CollaboratorAuthor

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.

Comment threadinclude/pybind11/pybind11.h Outdated
#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
Copy Markdown
CollaboratorAuthor

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.

@YannickJadoulYannickJadoul left a comment

Copy link
Copy Markdown
Collaborator

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 threadinclude/pybind11/pybind11.h Outdated
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
Copy Markdown
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?

Comment threadinclude/pybind11/pybind11.h Outdated
#if defined(__GNUG__) && !defined(__clang__) && __GNUC__ >= 6
# pragma GCC diagnostic pop
#endif
#if !PYBIND11_HAS_STD_LAUNDER

Copy link
Copy Markdown
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
#ifdefined(__GNUG__) &&!PYBIND11_HAS_STD_LAUNDER

or

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

@bstaletic
bstaleticforce-pushed the strict-aliasing branch 4 times, most recently from e7225e6 to 257af0eCompareJanuary 23, 2021 23:50
Comment threadinclude/pybind11/pybind11.h Outdated
@YannickJadoul

Copy link
Copy Markdown
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 <yannick.jadoul@belgacom.net>
@bstaletic

Copy link
Copy Markdown
CollaboratorAuthor

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

@henryiiihenryiii left a comment

Copy link
Copy Markdown
Collaborator

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
Copy Markdown
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
Copy Markdown
CollaboratorAuthor

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};
| ^

@rwgkrwgk left a comment

Copy link
Copy Markdown
Collaborator

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

rwgk commented Jul 15, 2021

Copy link
Copy Markdown
Collaborator

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:masterJul 15, 2021
@github-actionsgithub-actionsBot added the needs changelog Possibly needs a changelog entry label Jul 15, 2021
@henryiiihenryiii 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
@rwgkrwgk mentioned this pull request Feb 10, 2023
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 freeto 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

@bstaletic@YannickJadoul@Skylion007@rwgk@henryiii