From 4a6234d214534bb8f17132581902b80db0f57762 Mon Sep 17 00:00:00 2001 From: Robert Bradshaw Date: Thu, 22 Oct 2009 02:17:13 -0700 Subject: [PATCH] Fix casts and negations in except clauses. --- Cython/Compiler/ExprNodes.py | 10 ++++++++++ Cython/Compiler/Nodes.py | 2 +- Cython/Compiler/PyrexTypes.py | 11 +++++++++-- tests/run/exceptionpropagation.pyx | 14 ++++++++++++++ 4 files changed, 34 insertions(+), 3 deletions(-) diff --git a/Cython/Compiler/ExprNodes.py b/Cython/Compiler/ExprNodes.py index 9871eda3..284ba7c9 100644 --- a/Cython/Compiler/ExprNodes.py +++ b/Cython/Compiler/ExprNodes.py @@ -4106,6 +4106,11 @@ class UnaryMinusNode(UnopNode): else: return "%s(%s)" % (self.operand.type.unary_op('-'), self.operand.result()) + def get_constant_c_result_code(self): + value = self.operand.get_constant_c_result_code() + if value: + return "(-%s)" % (value) + class TildeNode(UnopNode): # unary '~' operator @@ -4251,6 +4256,11 @@ class TypecastNode(ExprNode): opnd = self.operand return self.type.cast_code(opnd.result()) + def get_constant_c_result_code(self): + operand_result = self.operand.get_constant_c_result_code() + if operand_result: + return self.type.cast_code(operand_result) + def result_as(self, type): if self.type.is_pyobject and not self.is_temp: # Optimise away some unnecessary casting diff --git a/Cython/Compiler/Nodes.py b/Cython/Compiler/Nodes.py index 97ea7461..9144f228 100644 --- a/Cython/Compiler/Nodes.py +++ b/Cython/Compiler/Nodes.py @@ -546,7 +546,6 @@ class CFuncDeclaratorNode(CDeclaratorNode): else: if self.exception_value: self.exception_value.analyse_const_expression(env) - exc_val = self.exception_value.get_constant_c_result_code() if self.exception_check == '+': exc_val_type = self.exception_value.type if not exc_val_type.is_error and \ @@ -555,6 +554,7 @@ class CFuncDeclaratorNode(CDeclaratorNode): error(self.exception_value.pos, "Exception value must be a Python exception or cdef function with no arguments.") else: + exc_val = self.exception_value.get_constant_c_result_code() if not return_type.assignable_from(self.exception_value.type): error(self.exception_value.pos, "Exception value incompatible with function return type") diff --git a/Cython/Compiler/PyrexTypes.py b/Cython/Compiler/PyrexTypes.py index 4a0dc00b..574096e1 100644 --- a/Cython/Compiler/PyrexTypes.py +++ b/Cython/Compiler/PyrexTypes.py @@ -1282,10 +1282,17 @@ class CFuncType(CType): arg_reprs = map(repr, self.args) if self.has_varargs: arg_reprs.append("...") - return "" % ( + if self.exception_value: + except_clause = " %r" % self.exception_value + else: + except_clause = "" + if self.exception_check: + except_clause += "?" + return "" % ( repr(self.return_type), self.calling_convention_prefix(), - ",".join(arg_reprs)) + ",".join(arg_reprs), + except_clause) def calling_convention_prefix(self): cc = self.calling_convention diff --git a/tests/run/exceptionpropagation.pyx b/tests/run/exceptionpropagation.pyx index e324a70a..eb157b86 100644 --- a/tests/run/exceptionpropagation.pyx +++ b/tests/run/exceptionpropagation.pyx @@ -15,3 +15,17 @@ cdef int obj2int(object ob) except *: def foo(a): cdef int i = obj2int(a) CHKERR(i) + +cdef int* except_expr(bint fire) except -1: + if fire: + raise RuntimeError + +def test_except_expr(bint fire): + """ + >>> test_except_expr(False) + >>> test_except_expr(True) + Traceback (most recent call last): + ... + RuntimeError + """ + except_expr(fire) -- 2.26.2