Skip to content

Commit

Permalink
Fix invalid C code with -DCYTHON_CCOMPLEX=0 when assigning a simple (…
Browse files Browse the repository at this point in the history
…integer) default value to a fused type generated complex argument (which ends up as a struct).

Closes cython#5643
  • Loading branch information
scoder committed Aug 26, 2023
1 parent 310720f commit 4630776
Show file tree
Hide file tree
Showing 3 changed files with 108 additions and 1 deletion.
2 changes: 1 addition & 1 deletion Cython/Compiler/FusedNode.py
Original file line number Diff line number Diff line change
Expand Up @@ -904,7 +904,7 @@ def analyse_expressions(self, env):
for arg, default in zip(stat.args, defaults):
if default is not None:
if default.is_literal:
arg.default = default
arg.default = default.coerce_to(arg.type, env)
else:
arg.default = CloneNode(default).analyse_expressions(env).coerce_to(arg.type, env)

Expand Down
49 changes: 49 additions & 0 deletions tests/run/fused_types.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -626,3 +626,52 @@ def test_null_default():
print(result, xf_minus_1)
result = null_default(xf)
print(result)


cdef cython.numeric fused_numeric_default(int a = 1, cython.numeric x = 0):
return x + a

def test_fused_numeric_default(int a, x):
"""
>>> test_fused_numeric_default(1, 0)
[1, 1.0, (1+0j)]
>>> test_fused_numeric_default(1, 2)
[3, 3.0, (3+0j)]
>>> test_fused_numeric_default(2, 0)
[2, 2.0, (2+0j)]
>>> test_fused_numeric_default(2, 1)
[3, 3.0, (3+0j)]
"""
result = []

if a == 1 and x == 0:
result.append(fused_numeric_default[int]())
elif x == 0:
result.append(fused_numeric_default[int](a))
elif a == 1:
result.append(fused_numeric_default[int](1, x))
else:
result.append(fused_numeric_default[int](a, x))

if a == 1 and x == 0:
result.append(fused_numeric_default[float]())
elif x == 0:
result.append(fused_numeric_default[float](a))
elif a == 1:
result.append(fused_numeric_default[float](1, x))
else:
result.append(fused_numeric_default[float](a, x))

if a == 1 and x == 0:
result.append(fused_numeric_default[cython.doublecomplex]())
elif x == 0:
result.append(fused_numeric_default[cython.doublecomplex](a))
elif a == 1:
result.append(fused_numeric_default[cython.doublecomplex](1, x))
else:
result.append(fused_numeric_default[cython.doublecomplex](a, x))

return result
58 changes: 58 additions & 0 deletions tests/run/fused_types_complex.pyx
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
# mode: run
# ticket: 5644
# cython: language_level=3
# distutils: define_macros=CYTHON_CCOMPLEX=0

cimport cython

# We used to generate invalid C code for the fused default value assignment
# (int -> complex) with CYTHON_CCOMPLEX=0.

cdef cython.numeric fused_numeric_default(int a = 1, cython.numeric x = 0):
return x + a


def test_fused_numeric_default(int a, x):
"""
>>> test_fused_numeric_default(1, 0)
[1, 1.0, (1+0j)]
>>> test_fused_numeric_default(1, 2)
[3, 3.0, (3+0j)]
>>> test_fused_numeric_default(2, 0)
[2, 2.0, (2+0j)]
>>> test_fused_numeric_default(2, 1)
[3, 3.0, (3+0j)]
"""
result = []

if a == 1 and x == 0:
result.append(fused_numeric_default[int]())
elif x == 0:
result.append(fused_numeric_default[int](a))
elif a == 1:
result.append(fused_numeric_default[int](1, x))
else:
result.append(fused_numeric_default[int](a, x))

if a == 1 and x == 0:
result.append(fused_numeric_default[float]())
elif x == 0:
result.append(fused_numeric_default[float](a))
elif a == 1:
result.append(fused_numeric_default[float](1, x))
else:
result.append(fused_numeric_default[float](a, x))

if a == 1 and x == 0:
result.append(fused_numeric_default[cython.doublecomplex]())
elif x == 0:
result.append(fused_numeric_default[cython.doublecomplex](a))
elif a == 1:
result.append(fused_numeric_default[cython.doublecomplex](1, x))
else:
result.append(fused_numeric_default[cython.doublecomplex](a, x))

return result

0 comments on commit 4630776

Please sign in to comment.