2
0
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:
denzor200
2023-08-19 17:13:29 +03:00
committed by Antony Polukhin
parent 3438d5e815
commit ad7ab1cfc3
7 changed files with 78 additions and 23 deletions

View File

@@ -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 {

View File

@@ -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

View File

@@ -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 {

View File

@@ -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 ] ]
;

View 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() {}

View File

@@ -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() {

View File

@@ -14,8 +14,6 @@
namespace testing {
namespace {
struct Aggregate {
int _%ARG%;
};
@@ -35,8 +33,6 @@ void test_names_as_array() {
}
}
} // anonymous namespace
} // namespace testing