Skip to content

Cython incorrectly casts with ctypedef and bint #3066

@mbuesch

Description

@mbuesch

Given the following code:

ctypedef bint mybool

cdef f():
        cdef mybool c
        cdef mybool x
        c = True
        x = True
        x = not x if c else x
        print(x)

Results in this C code:

/* "test.pyx":3
 * ctypedef bint mybool
 * 
 * cdef f():             # <<<<<<<<<<<<<<
 * 	cdef mybool c
 * 	cdef mybool x
 */

static PyObject *__pyx_f_4test_f(void) {
  __pyx_t_4test_mybool __pyx_v_c;
  __pyx_t_4test_mybool __pyx_v_x;
  PyObject *__pyx_r = NULL;
  __Pyx_RefNannyDeclarations
  PyObject *__pyx_t_1 = NULL;
  PyObject *__pyx_t_2 = NULL;
  __Pyx_RefNannySetupContext("f", 0);

  /* "test.pyx":6
 * 	cdef mybool c
 * 	cdef mybool x
 * 	c = True             # <<<<<<<<<<<<<<
 * 	x = True
 * 	x = not x if c else x
 */
  __pyx_v_c = 1;

  /* "test.pyx":7
 * 	cdef mybool x
 * 	c = True
 * 	x = True             # <<<<<<<<<<<<<<
 * 	x = not x if c else x
 * 	print(x)
 */
  __pyx_v_x = 1;

  /* "test.pyx":8
 * 	c = True
 * 	x = True
 * 	x = not x if c else x             # <<<<<<<<<<<<<<
 * 	print(x)
 */
  if ((__pyx_v_c != 0)) {
    __pyx_t_1 = ((PyObject *)(!(__pyx_v_x != 0)));
  } else {
    __pyx_t_1 = ((PyObject *)__pyx_v_x);
  }
  __pyx_v_x = ((__pyx_t_4test_mybool)__pyx_t_1);
  __pyx_t_1 = 0;

  /* "test.pyx":9
 * 	x = True
 * 	x = not x if c else x
 * 	print(x)             # <<<<<<<<<<<<<<
 */
  __pyx_t_1 = __Pyx_PyBool_FromLong(__pyx_v_x); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 9, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);
  __pyx_t_2 = __Pyx_PyObject_CallOneArg(__pyx_builtin_print, __pyx_t_1); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 9, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_2);
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;

  /* "test.pyx":3
 * ctypedef bint mybool
 * 
 * cdef f():             # <<<<<<<<<<<<<<
 * 	cdef mybool c
 * 	cdef mybool x
 */

  /* function exit code */
  __pyx_r = Py_None; __Pyx_INCREF(Py_None);
  goto __pyx_L0;
  __pyx_L1_error:;
  __Pyx_XDECREF(__pyx_t_1);
  __Pyx_XDECREF(__pyx_t_2);
  __Pyx_AddTraceback("test.f", __pyx_clineno, __pyx_lineno, __pyx_filename);
  __pyx_r = 0;
  __pyx_L0:;
  __Pyx_XGIVEREF(__pyx_r);
  __Pyx_RefNannyFinishContext();
  return __pyx_r;
}

Which throws these compiler warnings:

$ gcc -shared -pthread -fPIC -fwrapv -O2 -Wall -fno-strict-aliasing -I/usr/include/python3.7 -o test test.c 
test.c: In function ‘__pyx_f_4test_f’:
test.c:1136:18: warning: cast to pointer from integer of different size [-Wint-to-pointer-cast]
     __pyx_t_1 = ((PyObject *)(!(__pyx_v_x != 0)));
                  ^
test.c:1138:18: warning: cast to pointer from integer of different size [-Wint-to-pointer-cast]
     __pyx_t_1 = ((PyObject *)__pyx_v_x);
                  ^
test.c:1140:16: warning: cast from pointer to integer of different size [-Wpointer-to-int-cast]
   __pyx_v_x = ((__pyx_t_4test_mybool)__pyx_t_1);

The C boolean variable __pyx_v_x is incorrectly casted to PyObject * and back to bool.

This does not happen, if bint is used directly in the cdefs.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions