From a34771aedab7792aa97da67921f9ad23abfa6e82 Mon Sep 17 00:00:00 2001 From: "Ralf W. Grosse-Kunstleve" Date: Tue, 21 Jun 2022 18:12:22 -0700 Subject: [PATCH] Move cpp_version_in_use() from cast.h to pybind11_tests.cpp --- include/pybind11/cast.h | 68 +--------- include/pybind11/detail/type_caster_base.h | 35 +----- .../pybind11/detail/type_caster_odr_guard.h | 118 ++++++++++++++++++ tests/pybind11_tests.cpp | 15 ++- 4 files changed, 134 insertions(+), 102 deletions(-) create mode 100644 include/pybind11/detail/type_caster_odr_guard.h diff --git a/include/pybind11/cast.h b/include/pybind11/cast.h index ffc5ea985..8db22b844 100644 --- a/include/pybind11/cast.h +++ b/include/pybind11/cast.h @@ -14,6 +14,7 @@ #include "detail/descr.h" #include "detail/smart_holder_sfinae_hooks_only.h" #include "detail/type_caster_base.h" +#include "detail/type_caster_odr_guard.h" #include "detail/typeid.h" #include "pytypes.h" @@ -49,69 +50,8 @@ class type_caster : public type_caster_for_class_ {}; #ifdef PYBIND11_TYPE_CASTER_ODR_GUARD_ON -inline std::unordered_map &odr_guard_registry() { - static std::unordered_map reg; - return reg; -} - -inline const char *cpp_version_in_use() { - return -# if defined(PYBIND11_CPP20) - "C++20"; -# elif defined(PYBIND11_CPP17) - "C++17"; -# elif defined(PYBIND11_CPP14) - "C++14"; -# else - "C++11"; -# endif -} - -inline const char *source_file_line_basename(const char *sfl) { - unsigned i_base = 0; - for (unsigned i = 0; sfl[i] != '\0'; i++) { - if (sfl[i] == '/' || sfl[i] == '\\') { - i_base = i + 1; - } - } - return sfl + i_base; -} - namespace { -template -bool odr_guard_impl(const std::type_index &it_ti, const char *source_file_line) { - // std::cout cannot be used here: static initialization could be incomplete. -# define PYBIND11_DETAIL_ODR_GUARD_IMPL_PRINTF_OFF -# ifdef PYBIND11_DETAIL_ODR_GUARD_IMPL_PRINTF_ON - fprintf( - stdout, "\nODR_GUARD_IMPL %s %s\n", type_id().c_str(), source_file_line); - fflush(stdout); -# endif - std::string sflbn_str{source_file_line_basename(source_file_line)}; - auto ins = odr_guard_registry().insert({it_ti, source_file_line}); - auto reg_iter = ins.first; - auto added = ins.second; - if (!added - && strcmp(source_file_line_basename(reg_iter->second.c_str()), - source_file_line_basename(source_file_line)) - != 0) { - std::system_error err(std::make_error_code(std::errc::state_not_recoverable), - "ODR VIOLATION DETECTED (" + std::string(cpp_version_in_use()) - + "): pybind11::detail::type_caster<" + type_id() - + ">: SourceLocation1=\"" + reg_iter->second - + "\", SourceLocation2=\"" + source_file_line + "\""); -# define PYBIND11_TYPE_CASTER_ODR_GUARD_THROW_OFF -# ifdef PYBIND11_TYPE_CASTER_ODR_GUARD_THROW_ON - throw err; -# else - fprintf(stderr, "\nDISABLED std::system_error: %s\n", err.what()); - fflush(stderr); -# endif - } - return true; -} - template struct type_caster_odr_guard : type_caster { static int translation_unit_local; @@ -129,17 +69,11 @@ int type_caster_odr_guard::translation_unit_local = []() { template using make_caster = type_caster_odr_guard>; -# define PYBIND11_DETAIL_TYPE_CASTER_ACCESS_TRANSLATION_UNIT_LOCAL(...) \ - if (::pybind11::detail::make_caster<__VA_ARGS__>::translation_unit_local) { \ - } - #else // !PYBIND11_TYPE_CASTER_ODR_GUARD_ON template using make_caster = type_caster>; -# define PYBIND11_DETAIL_TYPE_CASTER_ACCESS_TRANSLATION_UNIT_LOCAL(...) - #endif template diff --git a/include/pybind11/detail/type_caster_base.h b/include/pybind11/detail/type_caster_base.h index 9c4cf4741..556d7afbf 100644 --- a/include/pybind11/detail/type_caster_base.h +++ b/include/pybind11/detail/type_caster_base.h @@ -13,6 +13,7 @@ #include "common.h" #include "descr.h" #include "internals.h" +#include "type_caster_odr_guard.h" #include "typeid.h" #include @@ -904,40 +905,6 @@ struct polymorphic_type_hook : public polymorphic_type_hook_base {}; PYBIND11_NAMESPACE_BEGIN(detail) -#if !defined(PYBIND11_TYPE_CASTER_ODR_GUARD_ON) && !defined(PYBIND11_TYPE_CASTER_ODR_GUARD_OFF) \ - && (defined(_MSC_VER) || defined(PYBIND11_CPP20) \ - || (defined(PYBIND11_CPP17) && defined(__clang__))) -# define PYBIND11_TYPE_CASTER_ODR_GUARD_ON -#endif - -#ifdef PYBIND11_TYPE_CASTER_ODR_GUARD_ON - -namespace { - -template -struct tu_local_descr : descr { - using descr_t = descr; - using descr_t::descr_t; -}; - -template -constexpr tu_local_descr tu_local_const_name(char const (&text)[N]) { - return tu_local_descr(text); -} -constexpr tu_local_descr<0> tu_local_const_name(char const (&)[1]) { return {}; } - -} // namespace - -# define PYBIND11_TYPE_CASTER_SOURCE_FILE_LINE \ - static constexpr auto source_file_line \ - = ::pybind11::detail::tu_local_const_name(__FILE__ ":" PYBIND11_TOSTRING(__LINE__)); - -#else // !PYBIND11_TYPE_CASTER_ODR_GUARD_ON - -# define PYBIND11_TYPE_CASTER_SOURCE_FILE_LINE - -#endif - /// Generic type caster for objects stored on the heap template class type_caster_base : public type_caster_generic { diff --git a/include/pybind11/detail/type_caster_odr_guard.h b/include/pybind11/detail/type_caster_odr_guard.h new file mode 100644 index 000000000..f0a42bccd --- /dev/null +++ b/include/pybind11/detail/type_caster_odr_guard.h @@ -0,0 +1,118 @@ +// Copyright (c) 2022 The Pybind Development Team. +// All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +#pragma once + +#if !defined(PYBIND11_TYPE_CASTER_ODR_GUARD_ON) && !defined(PYBIND11_TYPE_CASTER_ODR_GUARD_OFF) \ + && (defined(_MSC_VER) || defined(PYBIND11_CPP20) \ + || (defined(PYBIND11_CPP17) && defined(__clang__))) +# define PYBIND11_TYPE_CASTER_ODR_GUARD_ON +#endif + +#ifndef PYBIND11_TYPE_CASTER_ODR_GUARD_ON + +# define PYBIND11_TYPE_CASTER_SOURCE_FILE_LINE + +# define PYBIND11_DETAIL_TYPE_CASTER_ACCESS_TRANSLATION_UNIT_LOCAL(...) + +#else + +# include "common.h" +# include "descr.h" +# include "typeid.h" + +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include + +PYBIND11_NAMESPACE_BEGIN(PYBIND11_NAMESPACE) +PYBIND11_NAMESPACE_BEGIN(detail) + +inline std::unordered_map &odr_guard_registry() { + static std::unordered_map reg; + return reg; +} + +inline const char *source_file_line_basename(const char *sfl) { + unsigned i_base = 0; + for (unsigned i = 0; sfl[i] != '\0'; i++) { + if (sfl[i] == '/' || sfl[i] == '\\') { + i_base = i + 1; + } + } + return sfl + i_base; +} + +template +bool odr_guard_impl(const std::type_index &it_ti, const char *source_file_line) { + // std::cout cannot be used here: static initialization could be incomplete. +# define PYBIND11_DETAIL_ODR_GUARD_IMPL_PRINTF_OFF +# ifdef PYBIND11_DETAIL_ODR_GUARD_IMPL_PRINTF_ON + fprintf( + stdout, "\nODR_GUARD_IMPL %s %s\n", type_id().c_str(), source_file_line); + fflush(stdout); +# endif + std::string sflbn_str{source_file_line_basename(source_file_line)}; + auto ins = odr_guard_registry().insert({it_ti, source_file_line}); + auto reg_iter = ins.first; + auto added = ins.second; + if (!added + && strcmp(source_file_line_basename(reg_iter->second.c_str()), + source_file_line_basename(source_file_line)) + != 0) { + std::system_error err(std::make_error_code(std::errc::state_not_recoverable), + "ODR VIOLATION DETECTED: pybind11::detail::type_caster<" + + type_id() + ">: SourceLocation1=\"" + + reg_iter->second + "\", SourceLocation2=\"" + source_file_line + + "\""); +# define PYBIND11_TYPE_CASTER_ODR_GUARD_THROW_OFF +# ifdef PYBIND11_TYPE_CASTER_ODR_GUARD_THROW_ON + throw err; +# else + fprintf(stderr, "\nDISABLED std::system_error: %s\n", err.what()); + fflush(stderr); +# endif + } + return true; +} + +namespace { + +template +struct tu_local_descr : descr { + using descr_t = descr; + using descr_t::descr_t; +}; + +template +constexpr tu_local_descr tu_local_const_name(char const (&text)[N]) { + return tu_local_descr(text); +} +constexpr tu_local_descr<0> tu_local_const_name(char const (&)[1]) { return {}; } + +} // namespace + +PYBIND11_NAMESPACE_END(detail) +PYBIND11_NAMESPACE_END(PYBIND11_NAMESPACE) + +# define PYBIND11_TYPE_CASTER_SOURCE_FILE_LINE \ + static constexpr auto source_file_line \ + = ::pybind11::detail::tu_local_const_name(__FILE__ ":" PYBIND11_TOSTRING(__LINE__)); + +# define PYBIND11_DETAIL_TYPE_CASTER_ACCESS_TRANSLATION_UNIT_LOCAL(...) \ + if (::pybind11::detail::make_caster<__VA_ARGS__>::translation_unit_local) { \ + } + +#endif diff --git a/tests/pybind11_tests.cpp b/tests/pybind11_tests.cpp index 54355b06e..2f4a828f1 100644 --- a/tests/pybind11_tests.cpp +++ b/tests/pybind11_tests.cpp @@ -62,10 +62,23 @@ void bind_ConstructorStats(py::module_ &m) { }); } +const char *cpp_version_in_use() { + return +#if defined(PYBIND11_CPP20) + "C++20"; +#elif defined(PYBIND11_CPP17) + "C++17"; +#elif defined(PYBIND11_CPP14) + "C++14"; +#else + "C++11"; +#endif +} + PYBIND11_MODULE(pybind11_tests, m) { m.doc() = "pybind11 test module"; - m.attr("cpp_version_in_use") = py::detail::cpp_version_in_use(); + m.attr("cpp_version_in_use") = cpp_version_in_use(); m.attr("PYBIND11_INTERNALS_ID") = PYBIND11_INTERNALS_ID; bind_ConstructorStats(m);