type_caster_odr_guard_impl() cleanup

This commit is contained in:
Ralf W. Grosse-Kunstleve 2022-06-22 07:43:37 -07:00
parent 5d45055a58
commit 1acc9d0555
5 changed files with 34 additions and 24 deletions

View File

@ -56,9 +56,9 @@ struct type_caster_odr_guard : type_caster<IntrinsicType> {
template <typename IntrinsicType> template <typename IntrinsicType>
int type_caster_odr_guard<IntrinsicType>::translation_unit_local = []() { int type_caster_odr_guard<IntrinsicType>::translation_unit_local = []() {
odr_guard_impl<IntrinsicType>(std::type_index(typeid(IntrinsicType)), type_caster_odr_guard_impl(typeid(IntrinsicType),
type_caster<IntrinsicType>::source_file_line.text, type_caster<IntrinsicType>::source_file_line.text,
PYBIND11_DETAIL_ODR_GUARD_IMPL_THROW_DISABLED); PYBIND11_DETAIL_TYPE_CASTER_ODR_GUARD_IMPL_THROW_DISABLED);
return 0; return 0;
}(); }();

View File

@ -4,9 +4,11 @@
#pragma once #pragma once
// The type_caster ODR guard feature requires Translation-Unit-local entities
// (https://en.cppreference.com/w/cpp/language/tu_local), a C++20 feature, but
// all tested C++17 compilers support this feature already.
#if !defined(PYBIND11_TYPE_CASTER_ODR_GUARD_ON) && !defined(PYBIND11_TYPE_CASTER_ODR_GUARD_OFF) \ #if !defined(PYBIND11_TYPE_CASTER_ODR_GUARD_ON) && !defined(PYBIND11_TYPE_CASTER_ODR_GUARD_OFF) \
&& (defined(_MSC_VER) || defined(PYBIND11_CPP20) \ && (defined(_MSC_VER) || defined(PYBIND11_CPP17))
|| (defined(PYBIND11_CPP17) /* && defined(__clang__)*/))
# define PYBIND11_TYPE_CASTER_ODR_GUARD_ON # define PYBIND11_TYPE_CASTER_ODR_GUARD_ON
#endif #endif
@ -32,6 +34,7 @@
# include <string> # include <string>
# include <system_error> # include <system_error>
# include <typeindex> # include <typeindex>
# include <typeinfo>
# include <unordered_map> # include <unordered_map>
# include <utility> # include <utility>
@ -53,23 +56,24 @@ inline const char *source_file_line_basename(const char *sfl) {
return sfl + i_base; return sfl + i_base;
} }
# ifndef PYBIND11_DETAIL_ODR_GUARD_IMPL_THROW_DISABLED # ifndef PYBIND11_DETAIL_TYPE_CASTER_ODR_GUARD_IMPL_THROW_DISABLED
# define PYBIND11_DETAIL_ODR_GUARD_IMPL_THROW_DISABLED false # define PYBIND11_DETAIL_TYPE_CASTER_ODR_GUARD_IMPL_THROW_DISABLED false
# endif # endif
template <typename IntrinsicType> inline void type_caster_odr_guard_impl(const std::type_info &intrinsic_type_info,
void odr_guard_impl(const std::type_index &it_ti, const char *source_file_line,
const char *source_file_line, bool throw_disabled) {
bool throw_disabled) {
// std::cout cannot be used here: static initialization could be incomplete. // std::cout cannot be used here: static initialization could be incomplete.
# define PYBIND11_DETAIL_ODR_GUARD_IMPL_PRINTF_OFF # define PYBIND11_DETAIL_TYPE_CASTER_ODR_GUARD_IMPL_PRINTF_OFF
# ifdef PYBIND11_DETAIL_ODR_GUARD_IMPL_PRINTF_ON # ifdef PYBIND11_DETAIL_TYPE_CASTER_ODR_GUARD_IMPL_PRINTF_ON
std::fprintf( std::fprintf(stdout,
stdout, "\nODR_GUARD_IMPL %s %s\n", type_id<IntrinsicType>().c_str(), source_file_line); "\nTYPE_CASTER_ODR_GUARD_IMPL %s %s\n",
clean_type_id(intrinsic_type_info.name()).c_str(),
source_file_line);
std::fflush(stdout); std::fflush(stdout);
# endif # endif
std::string sflbn_str{source_file_line_basename(source_file_line)}; auto ins
auto ins = odr_guard_registry().insert({it_ti, source_file_line}); = odr_guard_registry().insert({std::type_index(intrinsic_type_info), source_file_line});
auto reg_iter = ins.first; auto reg_iter = ins.first;
auto added = ins.second; auto added = ins.second;
if (!added if (!added
@ -77,8 +81,8 @@ void odr_guard_impl(const std::type_index &it_ti,
source_file_line_basename(source_file_line)) source_file_line_basename(source_file_line))
!= 0) { != 0) {
std::string msg("ODR VIOLATION DETECTED: pybind11::detail::type_caster<" std::string msg("ODR VIOLATION DETECTED: pybind11::detail::type_caster<"
+ type_id<IntrinsicType>() + ">: SourceLocation1=\"" + reg_iter->second + clean_type_id(intrinsic_type_info.name()) + ">: SourceLocation1=\""
+ "\", SourceLocation2=\"" + source_file_line + "\""); + reg_iter->second + "\", SourceLocation2=\"" + source_file_line + "\"");
if (throw_disabled) { if (throw_disabled) {
std::fprintf(stderr, "\nDISABLED std::system_error: %s\n", msg.c_str()); std::fprintf(stderr, "\nDISABLED std::system_error: %s\n", msg.c_str());
std::fflush(stderr); std::fflush(stderr);

View File

@ -20,6 +20,7 @@
PYBIND11_NAMESPACE_BEGIN(PYBIND11_NAMESPACE) PYBIND11_NAMESPACE_BEGIN(PYBIND11_NAMESPACE)
PYBIND11_NAMESPACE_BEGIN(detail) PYBIND11_NAMESPACE_BEGIN(detail)
/// Erase all occurrences of a substring /// Erase all occurrences of a substring
inline void erase_all(std::string &string, const std::string &search) { inline void erase_all(std::string &string, const std::string &search) {
for (size_t pos = 0;;) { for (size_t pos = 0;;) {
@ -46,14 +47,19 @@ PYBIND11_NOINLINE void clean_type_id(std::string &name) {
#endif #endif
detail::erase_all(name, "pybind11::"); detail::erase_all(name, "pybind11::");
} }
inline std::string clean_type_id(const char *typeid_name) {
std::string name(typeid_name);
detail::clean_type_id(name);
return name;
}
PYBIND11_NAMESPACE_END(detail) PYBIND11_NAMESPACE_END(detail)
/// Return a string representation of a C++ type /// Return a string representation of a C++ type
template <typename T> template <typename T>
static std::string type_id() { static std::string type_id() {
std::string name(typeid(T).name()); return detail::clean_type_id(typeid(T).name());
detail::clean_type_id(name);
return name;
} }
PYBIND11_NAMESPACE_END(PYBIND11_NAMESPACE) PYBIND11_NAMESPACE_END(PYBIND11_NAMESPACE)

View File

@ -1,4 +1,4 @@
#define PYBIND11_DETAIL_ODR_GUARD_IMPL_THROW_DISABLED true #define PYBIND11_DETAIL_TYPE_CASTER_ODR_GUARD_IMPL_THROW_DISABLED true
#include "pybind11_tests.h" #include "pybind11_tests.h"
namespace mrc_ns { // minimal real caster namespace mrc_ns { // minimal real caster

View File

@ -1,4 +1,4 @@
#define PYBIND11_DETAIL_ODR_GUARD_IMPL_THROW_DISABLED true #define PYBIND11_DETAIL_TYPE_CASTER_ODR_GUARD_IMPL_THROW_DISABLED true
#include "pybind11_tests.h" #include "pybind11_tests.h"
namespace mrc_ns { // minimal real caster namespace mrc_ns { // minimal real caster