[libcudacxx] Add cuda::std::__stringize for compile-time values including function names#9299
[libcudacxx] Add cuda::std::__stringize for compile-time values including function names#9299andralex wants to merge 14 commits into
Conversation
Add `cuda::std::__pretty_nameof_fn<Fn>()`, the function-name counterpart of `__pretty_nameof<T>()`, returning the unqualified spelling of a function passed as a non-type template parameter (e.g. `"cudaStreamSynchronize"` for `cudaStreamSynchronize`). It is implemented by wrapping the function value in a class-template NTTP and reusing `__pretty_nameof` on that wrapper type, so it automatically inherits the same compiler support and quirk handling (GCC < 9 static storage, broken MSVC __FUNCSIG__, old-GCC device code). A leading `&` (clang/cudafe) and any namespace qualifier are trimmed, matching the proof of concept. Includes an in-header smoke test and a dedicated lit test.
|
/ok to test 2a766dc |
Do not strip the namespace qualifier from the function name, matching __pretty_nameof for types. The namespace qualification the compiler emits is relative to the wrapper's namespace, so global functions (e.g. CUDA runtime APIs) still come out unqualified. Make the in-header smoke test robust to compiler-dependent spelling of the inline ABI namespace (substring check), and update the lit test to expect the qualified spelling for a namespaced function.
|
/ok to test 6002c07 |
|
Note Reviews pausedIt looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
suggestion: WalkthroughAdds constexpr extraction of NTTP value spellings via ChangesValue pretty-name extraction for NTTPs
Comment |
There was a problem hiding this comment.
🧹 Nitpick comments (1)
libcudacxx/include/cuda/std/__utility/typeid.h (1)
225-237: ⚡ Quick winsuggestion: Add missing
@returntag to Doxygen comment.The function has a detailed
@briefbut lacks the mandatory@returntag. As per coding guidelines, Doxygen-documented functions with non-void return types must include//!@return``.Suggested addition
After line 231, add:
//! This is the function-name counterpart of `__pretty_nameof`. It supports the //! same set of compilers and the same compiler quirks, because it is implemented //! on top of `__pretty_nameof`. +//! `@return` A string view containing the function name, preserving namespace qualifiers. template <auto _Fn>Source: Coding guidelines
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Enterprise
Run ID: e9d9739c-8568-4032-a1da-94647ebb652b
📒 Files selected for processing (2)
libcudacxx/include/cuda/std/__utility/typeid.hlibcudacxx/test/libcudacxx/std/utilities/utility/typeid/pretty_nameof_fn.pass.cpp
This comment has been minimized.
This comment has been minimized.
…value The function-name wrapper trick generalizes to any value passed as a non-type template parameter. Add `cuda::std::__pretty_nameof_v<V>()`, the value counterpart of `__pretty_nameof<T>()`, returning the compiler's spelling of V (e.g. `"42"` for `42`, `"true"` for `true`). `__pretty_nameof_fn` is now implemented on top of `__pretty_nameof_v`, only adding the leading-'&' trim for function arguments. The exact spelling of a value is not guaranteed to be identical across compilers (e.g. unsigned suffix, char quoting, enumerator spelling); integral and boolean values are stable. Add a dedicated pretty_nameof_v lit test and a header smoke test.
|
/ok to test b781579 |
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (1)
libcudacxx/include/cuda/std/__utility/typeid.h (1)
244-246: ⚡ Quick winsuggestion: constrain
__pretty_nameof_fnto function/function-pointer NTTPs (e.g., via requires/SFINAE + function traits) so non-function values fail at compile time instead of silently behaving like__pretty_nameof_v.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Enterprise
Run ID: 1d4fff2e-44af-488f-aa5c-6c111b14dc65
📒 Files selected for processing (2)
libcudacxx/include/cuda/std/__utility/typeid.hlibcudacxx/test/libcudacxx/std/utilities/utility/typeid/pretty_nameof_v.pass.cpp
Minimize the API surface to a single entry point. __pretty_nameof_v now detects function (and function-pointer / member-function-pointer) arguments via type traits and drops the leading '&' that clang and cudafe prepend, so callers no longer need a separate __pretty_nameof_fn. Consolidate the function-name tests into pretty_nameof_v.pass.cpp and drop the now-redundant pretty_nameof_fn.pass.cpp.
|
/ok to test 6995224 |
There was a problem hiding this comment.
🧹 Nitpick comments (1)
libcudacxx/include/cuda/std/__utility/typeid.h (1)
247-250: 💤 Low valuesuggestion: The substr call on line 249 passes
ptrdiff_t(__sv.size())as the count argument when removing the first character. Sincesubstr(pos)with no count argument means "to the end," you can simplify to__sv = __sv.substr(1);for clarity.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Enterprise
Run ID: f2419596-05c6-40ff-bac0-a598aafc30b8
📒 Files selected for processing (2)
libcudacxx/include/cuda/std/__utility/typeid.hlibcudacxx/test/libcudacxx/std/utilities/utility/typeid/pretty_nameof_v.pass.cpp
Add coverage for an overloaded function, where the desired overload is selected with a cast in the template argument. The check is at namespace scope: inside a function body cudafe++ rewrites the cast back to the ambiguous bare name, so the disambiguating cast must be applied where the value is used as a template argument directly.
|
/ok to test d9c1636 |
|
/ok to test 13a5551 |
Two CI failures: - MSVC spells a bool NTTP as something other than "true"/"false", which broke the in-header smoke static_assert (and therefore every MSVC build that transitively includes typeid.h). Drop the bool exact-match; only integer literals are spelled identically across all compilers. Use a distinctness check instead. - The cast-disambiguated overload test failed under nvcc on CTK 12.0/12.9/13.0/ 13.3: cudafe++ rewrites static_cast<...>(overload) back to the ambiguous &overload (it happened to survive on the locally-tested CTK 13.2). Guard that case to non-CUDA compilation. Make the test robust to compiler-dependent value spellings: exact matches only for integer literals, distinctness for bool, substring checks for function names everywhere, and exact function-name matches gated to non-MSVC.
|
/ok to test e085586 |
Rename the generalized value-spelling facility to cuda::std::__stringize (and its internals __stringize_wrapper / __find_stringize), and rename the test to stringize.pass.cpp. The type-based __pretty_nameof is unchanged.
|
/ok to test fb8f675 |
Add an explicit @return tag to satisfy libcudacxx documentation requirements.
|
/ok to test 30cd5bc |
This comment has been minimized.
This comment has been minimized.
|
/ok to test 9f38b2b |
This comment has been minimized.
This comment has been minimized.
|
/ok to test 9f38b2b |
| { | ||
| // Trim the surrounding "__stringize_wrapper<" ... ">". | ||
| return __sv.substr(::cuda::std::__add_string_view_position( | ||
| __sv.find("__stringize_wrapper<"), ptrdiff_t(sizeof("__stringize_wrapper<")) - 1), |
There was a problem hiding this comment.
| __sv.find("__stringize_wrapper<"), ptrdiff_t(sizeof("__stringize_wrapper<")) - 1), | |
| __sv.find("__stringize_wrapper<"), static_cast<ptrdiff_t>(sizeof("__stringize_wrapper<")) - 1), |
| { | ||
| if (__sv.size() != 0 && __sv[0] == '&') | ||
| { | ||
| __sv = __sv.substr(1, ptrdiff_t(__sv.size())); |
There was a problem hiding this comment.
| __sv = __sv.substr(1, ptrdiff_t(__sv.size())); | |
| __sv = __sv.substr(1, static_cast<ptrdiff_t>(__sv.size())); |
| //! template parameter, e.g. `__stringize<42>()` yields `"42"` and | ||
| //! `__stringize<cudaStreamSynchronize>()` yields `"cudaStreamSynchronize"`. | ||
| //! | ||
| //! @return A string view containing the compiler's spelling of `_Vp`. |
There was a problem hiding this comment.
Should document @tparam as well
| return __sv; | ||
| } | ||
|
|
||
| #if !defined(_CCCL_NO_CONSTEXPR_PRETTY_NAMEOF) && !defined(_CCCL_BROKEN_MSVC_FUNCSIG) |
There was a problem hiding this comment.
Let's gate this behind _CCCL_ENABLE_DEBUG_MODE as well, no point wasting the compilers time in release builds as well.
| // unqualified name is present rather than matching it exactly. | ||
| static_assert(::cuda::std::__stringize<&::cuda::std::__add_string_view_position>().find("__add_string_view_position") | ||
| != -1); | ||
| #endif |
| [[nodiscard]] _CCCL_API constexpr __string_view __stringize() noexcept | ||
| { | ||
| __string_view __sv = | ||
| ::cuda::std::__find_stringize(::cuda::std::__pretty_nameof<::cuda::std::__stringize_wrapper<_Vp>>()); |
There was a problem hiding this comment.
Why do we need the wrapper? Can we not do decltype()?
|
/ok to test 0fd6c30 |
🥳 CI Workflow Results🟩 Finished in 1h 55m: Pass: 100%/118 | Total: 2d 17h | Max: 1h 15m | Hits: 61%/547971See results here. |
Summary
cuda::std::__pretty_nameof<T>()gives the spelling of a type (e.g."int"),but there was no equivalent for non-type template parameters. This PR adds a
single helper:
cuda::std::__stringize<V>()— returns the compiler's spelling of any valuepassed as a non-type template parameter (integral constants, enums, bools,
pointers, functions, ...). When the value is a function it transparently
produces the function's name.
(Original function-name proof of concept: https://godbolt.org/z/vM9f37zrr)
Implementation
The value is wrapped in a class-template NTTP (
__stringize_wrapper<V>) and__pretty_nameofis reused on that wrapper type, so the helper automaticallyinherits the same compiler support and quirk handling as
__pretty_nameof:constexpr __PRETTY_FUNCTION__,__FUNCSIG__(_CCCL_BROKEN_MSVC_FUNCSIG) fallback,_CCCL_NO_CONSTEXPR_PRETTY_NAMEOF).After trimming the wrapper, function arguments are detected via type traits
(
is_function/is_member_function_pointer) and the leading&thatclang/cudafe prepend is dropped, so functions yield just their name. Namespace
qualifiers are kept, matching
__pretty_nameoffor types; the qualification thecompiler emits is relative to the wrapper's namespace, so global functions (e.g.
CUDA runtime APIs) come out unqualified. The result is
constexprwherever__pretty_nameofis.Caveat on value spellings
The exact spelling of a non-function value is whatever the compiler emits and is
not guaranteed identical across compilers — e.g. an unsigned literal can be
"42"(g++) or"42U"(nvcc/EDG at constexpr time), acharmay be quoted, aboolmay be"true"or"1"(MSVC), and enumerators may be spelled by name orby a cast. Integer literals are spelled identically everywhere; the tests check
those exactly and use distinctness / substring checks otherwise.
Test plan
std/utilities/utility/typeid/stringize.pass.cpp(integers,bools, distinctness, free function,
&functionpointer form, kept namespacequalifier, overload-via-cast on host compilers) passes locally with nvcc 13.2
-fno-rttiand-Werror=all-warnings(C++17/20).static_asserts.typeid.pass.cppstill passes (shared header).pre-commit(clang-format, codespell) clean.