summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorstijn <stijn@ignitron.net>2023-11-13 16:04:40 +0100
committerDamien George <damien@micropython.org>2023-11-17 14:31:42 +1100
commita968888f69d94890e8851efe38ace3b9448552d7 (patch)
tree7ac93b59f763373e589bd27be4e235b46d29e4ef
parent92741a34388e85d07e26511ff81b27af99445f00 (diff)
py/obj: Fix mp_obj_is_type compilation with C++.
Fixes issue #12951. Signed-off-by: stijn <stijn@ignitron.net>
-rw-r--r--examples/usercmodule/cppexample/example.cpp7
-rw-r--r--py/misc.h11
-rw-r--r--py/obj.h8
3 files changed, 19 insertions, 7 deletions
diff --git a/examples/usercmodule/cppexample/example.cpp b/examples/usercmodule/cppexample/example.cpp
index 06809732a..2df832baa 100644
--- a/examples/usercmodule/cppexample/example.cpp
+++ b/examples/usercmodule/cppexample/example.cpp
@@ -1,9 +1,16 @@
extern "C" {
#include <examplemodule.h>
+#include <py/objstr.h>
// Here we implement the function using C++ code, but since it's
// declaration has to be compatible with C everything goes in extern "C" scope.
mp_obj_t cppfunc(mp_obj_t a_obj, mp_obj_t b_obj) {
+ // The following no-ops are just here to verify the static assertions used in
+ // the public API all compile with C++.
+ MP_STATIC_ASSERT_STR_ARRAY_COMPATIBLE;
+ if (mp_obj_is_type(a_obj, &mp_type_BaseException)) {
+ }
+
// Prove we have (at least) C++11 features.
const auto a = mp_obj_get_int(a_obj);
const auto b = mp_obj_get_int(b_obj);
diff --git a/py/misc.h b/py/misc.h
index 352a9f34c..e19a53572 100644
--- a/py/misc.h
+++ b/py/misc.h
@@ -52,10 +52,15 @@ typedef unsigned int uint;
// Static assertion macro
#define MP_STATIC_ASSERT(cond) ((void)sizeof(char[1 - 2 * !(cond)]))
-#if defined(_MSC_VER)
-#define MP_STATIC_ASSERT_NOT_MSC(cond) (1)
+// In C++ things like comparing extern const pointers are not constant-expressions so cannot be used
+// in MP_STATIC_ASSERT. Note that not all possible compiler versions will reject this. Some gcc versions
+// do, others only with -Werror=vla, msvc always does.
+// The (void) is needed to avoid "left operand of comma operator has no effect [-Werror=unused-value]"
+// when using this macro on the left-hand side of a comma.
+#if defined(_MSC_VER) || defined(__cplusplus)
+#define MP_STATIC_ASSERT_NONCONSTEXPR(cond) ((void)1)
#else
-#define MP_STATIC_ASSERT_NOT_MSC(cond) MP_STATIC_ASSERT(cond)
+#define MP_STATIC_ASSERT_NONCONSTEXPR(cond) MP_STATIC_ASSERT(cond)
#endif
// Round-up integer division
diff --git a/py/obj.h b/py/obj.h
index 56ae62172..c7b7db0c3 100644
--- a/py/obj.h
+++ b/py/obj.h
@@ -928,10 +928,10 @@ void *mp_obj_malloc_helper(size_t num_bytes, const mp_obj_type_t *type);
// optimizations (other tricks like using ({ expr; exper; }) or (exp, expr, expr) in mp_obj_is_type() result
// in missed optimizations)
#define mp_type_assert_not_bool_int_str_nonetype(t) ( \
- MP_STATIC_ASSERT_NOT_MSC((t) != &mp_type_bool), assert((t) != &mp_type_bool), \
- MP_STATIC_ASSERT_NOT_MSC((t) != &mp_type_int), assert((t) != &mp_type_int), \
- MP_STATIC_ASSERT_NOT_MSC((t) != &mp_type_str), assert((t) != &mp_type_str), \
- MP_STATIC_ASSERT_NOT_MSC((t) != &mp_type_NoneType), assert((t) != &mp_type_NoneType), \
+ MP_STATIC_ASSERT_NONCONSTEXPR((t) != &mp_type_bool), assert((t) != &mp_type_bool), \
+ MP_STATIC_ASSERT_NONCONSTEXPR((t) != &mp_type_int), assert((t) != &mp_type_int), \
+ MP_STATIC_ASSERT_NONCONSTEXPR((t) != &mp_type_str), assert((t) != &mp_type_str), \
+ MP_STATIC_ASSERT_NONCONSTEXPR((t) != &mp_type_NoneType), assert((t) != &mp_type_NoneType), \
1)
#define mp_obj_is_type(o, t) (mp_type_assert_not_bool_int_str_nonetype(t) && mp_obj_is_exact_type(o, t))