Skip to content

[BUG] unused variable warning when using -DCYTHON_WITHOUT_ASSERTIONS #3869

@jmd-dk

Description

@jmd-dk

Describe the bug
Compiling the generated C code with -DCYTHON_WITHOUT_ASSERTIONS removes asserts. One such assert is in format_from_typeinfo() in MemoryView.pyx:

assert type.fields != NULL and type.fields.type != NULL

The generated code looks like

#ifndef CYTHON_WITHOUT_ASSERTIONS
if (unlikely(!Py_OptimizeFlag)) {
  __pyx_t_2 = ((__pyx_v_type->fields != NULL) != 0);
  if (__pyx_t_2) {
  } else {
    __pyx_t_1 = __pyx_t_2;
    goto __pyx_L4_bool_binop_done;
  }
  __pyx_t_2 = ((__pyx_v_type->fields->type != NULL) != 0);
  __pyx_t_1 = __pyx_t_2;
  __pyx_L4_bool_binop_done:;
  if (unlikely(!__pyx_t_1)) {
    PyErr_SetNone(PyExc_AssertionError);
    __PYX_ERR(1, 1469, __pyx_L1_error)
  }
}
#endif

Here __pyx_t_2 is declared at the top of the function (together with other variables), but it is only ever used inside this #ifndef block. Thus, compiling with -DCYTHON_WITHOUT_ASSERTIONS (at least under gcc) emits the warning

warning: unused variable ‘__pyx_t_2’ [-Wunused-variable]
   int __pyx_t_2 = 0;

To Reproduce

cdef double[::1] ptr2view(double* ptr):
    cdef double[::1] a = <double[:3]>ptr
    return a

Environment

  • OS: Linux Mint 19.3
  • Python version: 3.8.2
  • Cython version: 0.29.16
  • C compiler: gcc 7.5.0

Proposed fix
The assert in question really asks two separate questions. Splitting them into two separate asserts solves the issue:

assert type.fields != NULL
assert type.fields.type != NULL

Note that as long as the order is preserved, this has the same behaviour as the combined assert. I believe the difference is that now, no additional, intermediate variable is needed to and together the two boolean expressions in the C code.

If we go with this fix, we should probably split all other "combined asserts" in a similar manner. A quick

grep -r 'assert ' | grep '\.pyx' | grep ' and '

reveals that the one in MemoryView.pyx is in fact the only one, not counting test code and documentation. The same goes for two asserts combined with or instead of and.

Bad code is of course still generated if a "combined assert" appears in the user code, e.g.

def f(a, b):
    assert a and b

but at least now no warnings will be emitted from Cython itself.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions