mirror of
https://github.com/boostorg/pfr.git
synced 2026-01-19 04:22:13 +00:00
Add Clang support
This commit is contained in:
committed by
Antony Polukhin
parent
3438d5e815
commit
ad7ab1cfc3
@@ -478,7 +478,7 @@ struct aggregate : empty { // not a SimpleAggregate
|
||||
The library may work with aggregates that don't satisfy the requirements of `SimpleAggregate`, but the behavior tends to be non-portable.
|
||||
|
||||
Boost.PFR's extraction of field name works with a `SimpleAggregate` which variables are able to be declared in any other translation unit.
|
||||
It's better not to use this feature with anonymous or local structure.
|
||||
It's better not to use this feature with anonymous structure, local structure or a structure defined inside anonymous namespace.
|
||||
|
||||
```
|
||||
struct external_simple_aggregate {
|
||||
|
||||
@@ -107,8 +107,12 @@
|
||||
#endif
|
||||
|
||||
#ifndef BOOST_PFR_ENABLE_GETTING_NAMES
|
||||
# if defined(__cpp_nontype_template_args) && __cpp_nontype_template_args >= 201911 && BOOST_PFR_FUNCTION_MACRO_SUPPORTED
|
||||
# define BOOST_PFR_ENABLE_GETTING_NAMES 1
|
||||
# if (defined(__cpp_nontype_template_args) && __cpp_nontype_template_args >= 201911) || (__cplusplus >= 202002L && defined(__clang_major__) && __clang_major__ >= 12)
|
||||
# if BOOST_PFR_FUNCTION_MACRO_SUPPORTED
|
||||
# define BOOST_PFR_ENABLE_GETTING_NAMES 1
|
||||
# else
|
||||
# define BOOST_PFR_ENABLE_GETTING_NAMES 0
|
||||
# endif
|
||||
# else
|
||||
# define BOOST_PFR_ENABLE_GETTING_NAMES 0
|
||||
# endif
|
||||
|
||||
@@ -30,15 +30,15 @@ constexpr auto make_sequence_tuple(Args... args) noexcept {
|
||||
return sequence_tuple::tuple<Args...>{ args... };
|
||||
}
|
||||
|
||||
template <typename MsvcWorkaround, auto* ptr>
|
||||
template <typename MsvcWorkaround, auto ptr>
|
||||
consteval auto name_of_field_impl() noexcept {
|
||||
#ifdef _MSC_VER
|
||||
constexpr std::string_view sv = __FUNCSIG__;
|
||||
// - strlen("(void)") - strlen(" noexcept")
|
||||
constexpr auto last = sv.find_last_not_of(" >(", sv.size() - 6 - 9);
|
||||
constexpr auto last = sv.find_last_not_of(" >(}", sv.size() - 6 - 9);
|
||||
#else
|
||||
constexpr std::string_view sv = __PRETTY_FUNCTION__;
|
||||
constexpr auto last = sv.find_last_not_of(" ])");
|
||||
constexpr auto last = sv.find_last_not_of(" ])}");
|
||||
#endif
|
||||
constexpr auto first = sv.find_last_not_of("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_0123456789", last);
|
||||
auto res = std::array<char, last - first + 2>{};
|
||||
@@ -51,11 +51,40 @@ consteval auto name_of_field_impl() noexcept {
|
||||
template <typename T>
|
||||
extern const T fake_object;
|
||||
|
||||
#ifdef __clang__
|
||||
#pragma clang diagnostic push
|
||||
#pragma clang diagnostic ignored "-Wundefined-var-template"
|
||||
|
||||
template<class T>
|
||||
struct clang_workaround_t {
|
||||
T v;
|
||||
};
|
||||
template<class T>
|
||||
clang_workaround_t(T) -> clang_workaround_t<T>;
|
||||
|
||||
template<typename T>
|
||||
constexpr auto clang_workaround(const T& arg) noexcept {
|
||||
return clang_workaround_t{arg};
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
template<typename T>
|
||||
constexpr const T& clang_workaround(const T& arg) noexcept {
|
||||
return arg;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
// Without passing 'T' into 'name_of_field_impl' different fields from different structures might have the same name!
|
||||
template <class T, std::size_t I>
|
||||
constexpr auto stored_name_of_field = name_of_field_impl<T, &detail::sequence_tuple::get<I>(
|
||||
constexpr auto stored_name_of_field = name_of_field_impl<T, clang_workaround(&detail::sequence_tuple::get<I>(
|
||||
detail::tie_as_tuple(fake_object<T>)
|
||||
)>();
|
||||
))>();
|
||||
|
||||
#ifdef __clang__
|
||||
#pragma clang diagnostic pop
|
||||
#endif
|
||||
|
||||
template <class T, std::size_t... I>
|
||||
constexpr auto tie_as_names_tuple_impl(std::index_sequence<I...>) noexcept {
|
||||
|
||||
@@ -12,7 +12,7 @@ import python ;
|
||||
import testing ;
|
||||
import ../../config/checks/config : requires ;
|
||||
|
||||
########## BEGIN of helpers to detect C++20 non-type template args support
|
||||
########## BEGIN of helpers to detect C++20 features support
|
||||
|
||||
actions mp_simple_run_action
|
||||
{
|
||||
@@ -31,17 +31,16 @@ rule mp-run-simple ( sources + : args * : input-files * : requirements * : targe
|
||||
mp-run-simple cxx20_nontype_template_args_detection.cpp : : : : compiler_supports_cxx20_nontype_template_args ;
|
||||
explicit compiler_supports_cxx20_nontype_template_args ;
|
||||
|
||||
########## END of helpers to detect C++20 non-type template args support
|
||||
mp-run-simple cxx20_clang_workaround_detection.cpp : : : : compiler_supports_cxx20_clang_workaround ;
|
||||
explicit compiler_supports_cxx20_clang_workaround ;
|
||||
|
||||
local REQUIRE_CXX20_NONTYPE_TEMPLATE_ARGS =
|
||||
[ check-target-builds ../core_name//compiler_supports_cxx20_nontype_template_args : : <build>no ]
|
||||
;
|
||||
########## END of helpers to detect C++20 features support
|
||||
|
||||
project
|
||||
: source-location .
|
||||
: requirements
|
||||
<define>BOOST_PFR_DETAIL_STRICT_RVALUE_TESTING=1
|
||||
[ check-target-builds ../core_name//compiler_supports_cxx20_nontype_template_args : : <build>no ]
|
||||
[ check-target-builds ../core_name//compiler_supports_cxx20_nontype_template_args : : [ check-target-builds ../core_name//compiler_supports_cxx20_clang_workaround : : <build>no ] ]
|
||||
;
|
||||
|
||||
|
||||
|
||||
32
test/core_name/cxx20_clang_workaround_detection.cpp
Normal file
32
test/core_name/cxx20_clang_workaround_detection.cpp
Normal file
@@ -0,0 +1,32 @@
|
||||
// Copyright (c) 2023 Bela Schaum, X-Ryl669, Denis Mikhailov.
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
|
||||
// Initial implementation by Bela Schaum, https://github.com/schaumb
|
||||
// The way to make it union and UB free by X-Ryl669, https://github.com/X-Ryl669
|
||||
//
|
||||
|
||||
template <auto p>
|
||||
class X {};
|
||||
|
||||
template <class T>
|
||||
struct Store
|
||||
{
|
||||
T v;
|
||||
};
|
||||
|
||||
template <class T>
|
||||
Store(T) -> Store<T>;
|
||||
|
||||
struct S
|
||||
{
|
||||
int m;
|
||||
} s;
|
||||
|
||||
X<Store{&s.m}> x4;
|
||||
|
||||
int main() {}
|
||||
|
||||
|
||||
@@ -16,8 +16,6 @@
|
||||
|
||||
namespace testing {
|
||||
|
||||
namespace {
|
||||
|
||||
struct nonconstexpr {
|
||||
nonconstexpr() {};
|
||||
};
|
||||
@@ -67,9 +65,6 @@ void test_names_as_array() {
|
||||
}
|
||||
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
|
||||
} // namespace testing
|
||||
|
||||
int main() {
|
||||
|
||||
@@ -14,8 +14,6 @@
|
||||
|
||||
namespace testing {
|
||||
|
||||
namespace {
|
||||
|
||||
struct Aggregate {
|
||||
int _%ARG%;
|
||||
};
|
||||
@@ -35,8 +33,6 @@ void test_names_as_array() {
|
||||
}
|
||||
}
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
|
||||
} // namespace testing
|
||||
|
||||
|
||||
Reference in New Issue
Block a user