Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Removing MSVC C4996 from pragma block at the top of pybind11.h #3129

Merged
merged 3 commits into from
Jul 26, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 24 additions & 9 deletions include/pybind11/chrono.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,14 @@
#pragma once

#include "pybind11.h"

#include <chrono>
#include <cmath>
#include <ctime>
#include <chrono>
#include <mutex>

#include <time.h>

#include <datetime.h>

// Backport the PyDateTime_DELTA functions from Python3.3 if required
Expand Down Expand Up @@ -95,6 +100,22 @@ template <typename type> class duration_caster {
PYBIND11_TYPE_CASTER(type, _("datetime.timedelta"));
};

inline std::tm *localtime_thread_safe(const std::time_t *time, std::tm *buf) {
#if defined(__STDC_WANT_LIB_EXT1__) || defined(_MSC_VER)
if (localtime_s(buf, time))
return nullptr;
return buf;
#else
static std::mutex mtx;
std::lock_guard<std::mutex> lock(mtx);
std::tm *tm_ptr = localtime(time);
if (tm_ptr != nullptr) {
*buf = *tm_ptr;
}
return tm_ptr;
#endif
}

// This is for casting times on the system clock into datetime.datetime instances
template <typename Duration> class type_caster<std::chrono::time_point<std::chrono::system_clock, Duration>> {
public:
Expand Down Expand Up @@ -162,16 +183,10 @@ template <typename Duration> class type_caster<std::chrono::time_point<std::chro
// (https://en.cppreference.com/w/cpp/chrono/system_clock/to_time_t)
std::time_t tt = system_clock::to_time_t(time_point_cast<system_clock::duration>(src - us));

// std::localtime returns a pointer to a static internal std::tm object on success,
// or null pointer otherwise
std::tm *localtime_ptr = std::localtime(&tt);
std::tm localtime;
std::tm *localtime_ptr = localtime_thread_safe(&tt, &localtime);
if (!localtime_ptr)
throw cast_error("Unable to represent system_clock in local time");

// this function uses static memory so it's best to copy it out asap just in case
// otherwise other code that is using localtime may break this (not just python code)
std::tm localtime = *localtime_ptr;

return PyDateTime_FromDateAndTime(localtime.tm_year + 1900,
localtime.tm_mon + 1,
localtime.tm_mday,
Expand Down
5 changes: 5 additions & 0 deletions include/pybind11/detail/common.h
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,11 @@
# endif
#endif

// https://en.cppreference.com/w/c/chrono/localtime
#if defined(__STDC_LIB_EXT1__) && !defined(__STDC_WANT_LIB_EXT1__)
# define __STDC_WANT_LIB_EXT1__
#endif

#include <Python.h>
#include <frameobject.h>
#include <pythread.h>
Expand Down
19 changes: 13 additions & 6 deletions include/pybind11/pybind11.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@
# pragma warning(disable: 4100) // warning C4100: Unreferenced formal parameter
# pragma warning(disable: 4127) // warning C4127: Conditional expression is constant
# pragma warning(disable: 4800) // warning C4800: 'int': forcing value to bool 'true' or 'false' (performance warning)
# pragma warning(disable: 4996) // warning C4996: The POSIX name for this item is deprecated. Instead, use the ISO C and C++ conformant name
# pragma warning(disable: 4522) // warning C4522: multiple assignment operators specified
# pragma warning(disable: 4505) // warning C4505: 'PySlice_GetIndicesEx': unreferenced local function has been removed (PyPy only)
#elif defined(__GNUG__) && !defined(__clang__)
Expand All @@ -43,6 +42,8 @@
#include <string>
#include <utility>

#include <string.h>

#if defined(__cpp_lib_launder) && !(defined(_MSC_VER) && (_MSC_VER < 1914))
# define PYBIND11_STD_LAUNDER std::launder
# define PYBIND11_HAS_STD_LAUNDER 1
Expand Down Expand Up @@ -76,8 +77,13 @@ inline bool apply_exception_translators(std::forward_list<ExceptionTranslator>&
return false;
}

PYBIND11_NAMESPACE_END(detail)
#if defined(_MSC_VER)
# define PYBIND11_COMPAT_STRDUP _strdup
#else
# define PYBIND11_COMPAT_STRDUP strdup
#endif

PYBIND11_NAMESPACE_END(detail)

/// Wraps an arbitrary C++ function/method/lambda function/.. into a callable Python object
class cpp_function : public function {
Expand Down Expand Up @@ -276,7 +282,7 @@ class cpp_function : public function {
std::free(s);
}
char *operator()(const char *s) {
auto t = strdup(s);
auto t = PYBIND11_COMPAT_STRDUP(s);
strings.push_back(t);
return t;
}
Expand Down Expand Up @@ -520,7 +526,8 @@ class cpp_function : public function {
auto *func = (PyCFunctionObject *) m_ptr;
std::free(const_cast<char *>(func->m_ml->ml_doc));
// Install docstring if it's non-empty (when at least one option is enabled)
func->m_ml->ml_doc = signatures.empty() ? nullptr : strdup(signatures.c_str());
func->m_ml->ml_doc
= signatures.empty() ? nullptr : PYBIND11_COMPAT_STRDUP(signatures.c_str());

if (rec->is_method) {
m_ptr = PYBIND11_INSTANCE_METHOD_NEW(m_ptr, rec->scope.ptr());
Expand Down Expand Up @@ -1525,15 +1532,15 @@ class class_ : public detail::generic_type {
detail::process_attributes<Extra...>::init(extra..., rec_fget);
if (rec_fget->doc && rec_fget->doc != doc_prev) {
free(doc_prev);
rec_fget->doc = strdup(rec_fget->doc);
rec_fget->doc = PYBIND11_COMPAT_STRDUP(rec_fget->doc);
}
}
if (rec_fset) {
char *doc_prev = rec_fset->doc;
detail::process_attributes<Extra...>::init(extra..., rec_fset);
if (rec_fset->doc && rec_fset->doc != doc_prev) {
free(doc_prev);
rec_fset->doc = strdup(rec_fset->doc);
rec_fset->doc = PYBIND11_COMPAT_STRDUP(rec_fset->doc);
}
if (! rec_active) rec_active = rec_fset;
}
Expand Down