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 +#include // 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))