Commit bd57eb48 by Wenzel Jakob

don't try to cast 'None' into a C++ lvalue reference

parent bdd11030
...@@ -21,7 +21,7 @@ void init_issues(py::module &m) { ...@@ -21,7 +21,7 @@ void init_issues(py::module &m) {
// #70 compilation issue if operator new is not public // #70 compilation issue if operator new is not public
class NonConstructible { private: void *operator new(size_t bytes) throw(); }; class NonConstructible { private: void *operator new(size_t bytes) throw(); };
py::class_<NonConstructible>(m, "Foo"); py::class_<NonConstructible>(m, "Foo");
m.def("getstmt", []() -> NonConstructible * { return nullptr; }, m2.def("getstmt", []() -> NonConstructible * { return nullptr; },
py::return_value_policy::reference); py::return_value_policy::reference);
#endif #endif
...@@ -101,4 +101,7 @@ void init_issues(py::module &m) { ...@@ -101,4 +101,7 @@ void init_issues(py::module &m) {
list.append(py::cast(e)); list.append(py::cast(e));
return list; return list;
}); });
};
// (no id): should not be able to pass 'None' to a reference argument
m2.def("print_element", [](ElementA &el) { std::cout << el.value() << std::endl; });
}
...@@ -7,7 +7,7 @@ from example.issues import print_cchar, print_char ...@@ -7,7 +7,7 @@ from example.issues import print_cchar, print_char
from example.issues import DispatchIssue, dispatch_issue_go from example.issues import DispatchIssue, dispatch_issue_go
from example.issues import Placeholder, return_vec_of_reference_wrapper from example.issues import Placeholder, return_vec_of_reference_wrapper
from example.issues import iterator_passthrough from example.issues import iterator_passthrough
from example.issues import ElementList, ElementA from example.issues import ElementList, ElementA, print_element
import gc import gc
print_cchar("const char *") print_cchar("const char *")
...@@ -42,3 +42,8 @@ gc.collect() ...@@ -42,3 +42,8 @@ gc.collect()
for i, v in enumerate(el.get()): for i, v in enumerate(el.get()):
print("%i==%i, " % (i, v.value()), end='') print("%i==%i, " % (i, v.value()), end='')
print() print()
try:
print_element(None)
except Exception as e:
print("Failed as expected: " + str(e))
...@@ -5,3 +5,6 @@ Yay.. ...@@ -5,3 +5,6 @@ Yay..
[Placeholder[1], Placeholder[2], Placeholder[3], Placeholder[4]] [Placeholder[1], Placeholder[2], Placeholder[3], Placeholder[4]]
[3, 5, 7, 9, 11, 13, 15] [3, 5, 7, 9, 11, 13, 15]
0==0, 1==1, 2==2, 3==3, 4==4, 5==5, 6==6, 7==7, 8==8, 9==9, 0==0, 1==1, 2==2, 3==3, 4==4, 5==5, 6==6, 7==7, 8==8, 9==9,
Failed as expected: Incompatible function arguments. The following argument types are supported:
1. (example.issues.ElementA) -> NoneType
...@@ -225,6 +225,8 @@ using cast_op_type = typename std::conditional<std::is_pointer<typename std::rem ...@@ -225,6 +225,8 @@ using cast_op_type = typename std::conditional<std::is_pointer<typename std::rem
typename std::add_pointer<typename intrinsic_type<T>::type>::type, typename std::add_pointer<typename intrinsic_type<T>::type>::type,
typename std::add_lvalue_reference<typename intrinsic_type<T>::type>::type>::type; typename std::add_lvalue_reference<typename intrinsic_type<T>::type>::type>::type;
/// Thrown then trying to cast a null pointer into a reference argument
class invalid_reference_cast : public std::exception { };
/// Generic type caster for objects stored on the heap /// Generic type caster for objects stored on the heap
template <typename type> class type_caster_base : public type_caster_generic { template <typename type> class type_caster_base : public type_caster_generic {
...@@ -254,7 +256,7 @@ public: ...@@ -254,7 +256,7 @@ public:
template <typename T> using cast_op_type = pybind11::detail::cast_op_type<T>; template <typename T> using cast_op_type = pybind11::detail::cast_op_type<T>;
operator type*() { return (type *) value; } operator type*() { return (type *) value; }
operator type&() { return *((type *) value); } operator type&() { if (!value) throw invalid_reference_cast(); return *((type *) value); }
protected: protected:
typedef void *(*Constructor)(const void *stream); typedef void *(*Constructor)(const void *stream);
......
...@@ -409,8 +409,13 @@ protected: ...@@ -409,8 +409,13 @@ protected:
} }
} }
} }
try {
if (kwargs_consumed == nkwargs) if (kwargs_consumed == nkwargs)
result = it->impl(it, args_, parent); result = it->impl(it, args_, parent);
} catch (detail::invalid_reference_cast &) {
result = PYBIND11_TRY_NEXT_OVERLOAD;
}
if (result.ptr() != PYBIND11_TRY_NEXT_OVERLOAD) if (result.ptr() != PYBIND11_TRY_NEXT_OVERLOAD)
break; break;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment