[clang] [clang] Add `clang::behaves_like_std(...)` attribute (PR #76596)

Max Winkler via cfe-commits cfe-commits at lists.llvm.org
Sat Dec 30 16:30:32 PST 2023


MaxEW707 wrote:

> I don't know whether all of these things should be handled with the same attribute, or whether they should be handled at all, but they should definitely be considered when designing this attribute.

For this I am more concerned with language level features such as move, forward, reserved placement operator new, etc and not all generic std functions. I can see where that becomes muddy.

For example `to_integer`, `to_underlying` or `identity::operator` I don't view as language level features that require a `std` implementation. I view them as a larger issue with high level operations being poorly represented by the language itself.
I would love `operator->` and `operator*` on smart pointers that just return a member variable to be replaced with a direct field access.
I would love for bitwise operators on enum class types to be replaced directly with the builtin bitwise operation on the underlying type instead of a function call.

I would love for `std::byte` to be a builtin type in the compiler like `char8_t` and not be implemented in the std with a special check inside clang for `isStdByte`. Thankfully we can workaround this with the `may_alias` attribute on clang for our own enum class byte type.

I would also love for `std::initializer_list` to be a builtin type without this delicate dance with the std and the compiler on specific signatures for the constructor. Look at how MSVC defines `std::initializer_list`.

I foresee the compiler increasing making assumptions about the names of functions and types inside the std namespace like `std::to_underlying`, `std::byte`, etc. `clang::behaves_like_std` gives users an easy to tell the compiler to make those same assumptions with user defined names.

There are cases where the std functions have other implicit properties. Reserved placement operator new can be assumed to not have to check the returned pointer for null. If you implement your own placement operator new you do not get this benefit. MSVC only removes this check for the reserved placement new but thankfully provides the define `__PLACEMENT_NEW_INLINE` if you decide to define it yourself. I believe you can work this with the `returns_nonnull` attribute on clang when I checked some months back. However clang still does the function call in debug if you are not the global reserved placement operator new which sucks.

Maybe for stuff like `operator->` on a smart pointer the compiler will start looking at `std::unique_ptr::operator->`.
Maybe for these facilities we instead have a more generic attribute like `[[clang::treat_as_macro]]` which more closely aligns with the semantics of `mvsc::intrinsic`.
Maybe we improve `always_inline` code gen for small functions like `std::move` and `operator->` on a object that just returns its member variable to have the same assembly in debug as if those functions were implemented like macros.

I haven't thought too much about those other cases yet but if `always_inline` on `MyMove` produced the same code in debug as `std::move` that gets me 90% of what I want and that would also probably fix all the other small function calls.
My 2c.

https://github.com/llvm/llvm-project/pull/76596


More information about the cfe-commits mailing list