Commit 5ace507f authored by scoder's avatar scoder

Merge pull request #50 from vitek/_unused_args

Silence warning about unused args
parents c6c039bd 7306e1ec
...@@ -1205,6 +1205,8 @@ class CCodeWriter(object): ...@@ -1205,6 +1205,8 @@ class CCodeWriter(object):
return return
if storage_class: if storage_class:
self.put("%s " % storage_class) self.put("%s " % storage_class)
if not entry.cf_used:
self.put('CYTHON_UNUSED ')
self.put(entry.type.declaration_code( self.put(entry.type.declaration_code(
entry.cname, dll_linkage = dll_linkage)) entry.cname, dll_linkage = dll_linkage))
if entry.init is not None: if entry.init is not None:
......
import cython import cython
cython.declare(PyrexTypes=object, Naming=object, ExprNodes=object, Nodes=object, cython.declare(PyrexTypes=object, Naming=object, ExprNodes=object, Nodes=object,
Options=object, UtilNodes=object, ModuleNode=object, Options=object, UtilNodes=object, ModuleNode=object,
...@@ -145,7 +144,8 @@ class ControlFlow(object): ...@@ -145,7 +144,8 @@ class ControlFlow(object):
if entry.type.is_array or entry.type.is_struct_or_union: if entry.type.is_array or entry.type.is_struct_or_union:
return False return False
return (entry.is_local or entry.is_pyclass_attr or entry.is_arg or return (entry.is_local or entry.is_pyclass_attr or entry.is_arg or
entry.from_closure or entry.in_closure or entry.error_on_uninitialized) entry.from_closure or entry.in_closure or
entry.error_on_uninitialized)
def mark_position(self, node): def mark_position(self, node):
"""Mark position, will be used to draw graph nodes.""" """Mark position, will be used to draw graph nodes."""
...@@ -501,18 +501,21 @@ def check_definitions(flow, compiler_directives): ...@@ -501,18 +501,21 @@ def check_definitions(flow, compiler_directives):
# Unused result # Unused result
for assmt in assignments: for assmt in assignments:
if not assmt.refs and not assmt.entry.is_pyclass_attr \ if (not assmt.refs and not assmt.entry.is_pyclass_attr
and not assmt.entry.in_closure: and not assmt.entry.in_closure):
if assmt.entry.cf_references and warn_unused_result: if assmt.entry.cf_references and warn_unused_result:
if assmt.is_arg: if assmt.is_arg:
messages.warning(assmt.pos, "Unused argument value '%s'" % assmt.entry.name) messages.warning(assmt.pos, "Unused argument value '%s'" %
assmt.entry.name)
else: else:
messages.warning(assmt.pos, "Unused result in '%s'" % assmt.entry.name) messages.warning(assmt.pos, "Unused result in '%s'" %
assmt.entry.name)
assmt.lhs.cf_used = False assmt.lhs.cf_used = False
# Unused entries # Unused entries
for entry in flow.entries: for entry in flow.entries:
if not entry.cf_references and not entry.is_pyclass_attr and not entry.in_closure: if (not entry.cf_references and not entry.is_pyclass_attr
and not entry.in_closure):
# TODO: starred args entries are not marked with is_arg flag # TODO: starred args entries are not marked with is_arg flag
for assmt in entry.cf_assignments: for assmt in entry.cf_assignments:
if assmt.is_arg: if assmt.is_arg:
...@@ -522,13 +525,13 @@ def check_definitions(flow, compiler_directives): ...@@ -522,13 +525,13 @@ def check_definitions(flow, compiler_directives):
is_arg = False is_arg = False
if is_arg: if is_arg:
if warn_unused_arg: if warn_unused_arg:
messages.warning(entry.pos, "Unused argument '%s'" % entry.name) messages.warning(entry.pos, "Unused argument '%s'" %
# TODO: handle unused arguments entry.name)
entry.cf_used = True
else: else:
if warn_unused: if warn_unused:
messages.warning(entry.pos, "Unused entry '%s'" % entry.name) messages.warning(entry.pos, "Unused entry '%s'" %
entry.cf_used = False entry.name)
entry.cf_used = False
messages.report() messages.report()
...@@ -711,7 +714,9 @@ class CreateControlFlowGraph(CythonTransform): ...@@ -711,7 +714,9 @@ class CreateControlFlowGraph(CythonTransform):
if arg.is_name: if arg.is_name:
entry = arg.entry or self.env.lookup(arg.name) entry = arg.entry or self.env.lookup(arg.name)
if entry.in_closure or entry.from_closure: if entry.in_closure or entry.from_closure:
error(arg.pos, "can not delete variable '%s' referenced in nested scope" % entry.name) error(arg.pos,
"can not delete variable '%s' "
"referenced in nested scope" % entry.name)
# Mark reference # Mark reference
self.visit(arg) self.visit(arg)
self.flow.mark_deletion(arg, entry) self.flow.mark_deletion(arg, entry)
...@@ -1096,7 +1101,8 @@ class CreateControlFlowGraph(CythonTransform): ...@@ -1096,7 +1101,8 @@ class CreateControlFlowGraph(CythonTransform):
self.flow.mark_assignment(node.target, self.flow.mark_assignment(node.target,
object_expr, self.env.lookup(node.name)) object_expr, self.env.lookup(node.name))
# TODO: add negative attribute list to "visitchildren"? # TODO: add negative attribute list to "visitchildren"?
self.visitchildren(node, attrs=['dict', 'metaclass', 'mkw', 'bases', 'classobj']) self.visitchildren(node, attrs=['dict', 'metaclass',
'mkw', 'bases', 'classobj'])
self.env_stack.append(self.env) self.env_stack.append(self.env)
self.env = node.scope self.env = node.scope
self.flow.nextblock() self.flow.nextblock()
......
...@@ -1670,6 +1670,7 @@ class CFuncDefNode(FuncDefNode): ...@@ -1670,6 +1670,7 @@ class CFuncDefNode(FuncDefNode):
inline_in_pxd = False inline_in_pxd = False
decorators = None decorators = None
directive_locals = None directive_locals = None
override = None
def unqualified_name(self): def unqualified_name(self):
return self.entry.name return self.entry.name
...@@ -1792,12 +1793,22 @@ class CFuncDefNode(FuncDefNode): ...@@ -1792,12 +1793,22 @@ class CFuncDefNode(FuncDefNode):
return False return False
def generate_function_header(self, code, with_pymethdef, with_opt_args = 1, with_dispatch = 1, cname = None): def generate_function_header(self, code, with_pymethdef, with_opt_args = 1, with_dispatch = 1, cname = None):
scope = self.local_scope
arg_decls = [] arg_decls = []
type = self.type type = self.type
for arg in type.args[:len(type.args)-type.optional_arg_count]: for arg in type.args[:len(type.args)-type.optional_arg_count]:
arg_decls.append(arg.declaration_code()) arg_decl = arg.declaration_code()
entry = scope.lookup(arg.name)
if not entry.cf_used:
arg_decl = 'CYTHON_UNUSED %s' % arg_decl
arg_decls.append(arg_decl)
if with_dispatch and self.overridable: if with_dispatch and self.overridable:
arg_decls.append(PyrexTypes.c_int_type.declaration_code(Naming.skip_dispatch_cname)) dispatch_arg = PyrexTypes.c_int_type.declaration_code(
Naming.skip_dispatch_cname)
if self.override:
arg_decls.append(dispatch_arg)
else:
arg_decls.append('CYTHON_UNUSED %s' % dispatch_arg)
if type.optional_arg_count and with_opt_args: if type.optional_arg_count and with_opt_args:
arg_decls.append(type.op_arg_struct.declaration_code(Naming.optional_args_cname)) arg_decls.append(type.op_arg_struct.declaration_code(Naming.optional_args_cname))
if type.has_varargs: if type.has_varargs:
...@@ -1823,28 +1834,40 @@ class CFuncDefNode(FuncDefNode): ...@@ -1823,28 +1834,40 @@ class CFuncDefNode(FuncDefNode):
code.putln("%s%s%s {" % (storage_class, modifiers, header)) code.putln("%s%s%s {" % (storage_class, modifiers, header))
def generate_argument_declarations(self, env, code): def generate_argument_declarations(self, env, code):
scope = self.local_scope
for arg in self.args: for arg in self.args:
if arg.default: if arg.default:
result = arg.calculate_default_value_code(code) entry = scope.lookup(arg.name)
code.putln('%s = %s;' % ( if self.override or entry.cf_used:
arg.type.declaration_code(arg.cname), result)) result = arg.calculate_default_value_code(code)
code.putln('%s = %s;' % (
arg.type.declaration_code(arg.cname), result))
def generate_keyword_list(self, code): def generate_keyword_list(self, code):
pass pass
def generate_argument_parsing_code(self, env, code): def generate_argument_parsing_code(self, env, code):
i = 0 i = 0
used = 0
if self.type.optional_arg_count: if self.type.optional_arg_count:
scope = self.local_scope
code.putln('if (%s) {' % Naming.optional_args_cname) code.putln('if (%s) {' % Naming.optional_args_cname)
for arg in self.args: for arg in self.args:
if arg.default: if arg.default:
code.putln('if (%s->%sn > %s) {' % (Naming.optional_args_cname, Naming.pyrex_prefix, i)) entry = scope.lookup(arg.name)
declarator = arg.declarator if self.override or entry.cf_used:
while not hasattr(declarator, 'name'): code.putln('if (%s->%sn > %s) {' %
declarator = declarator.base (Naming.optional_args_cname,
code.putln('%s = %s->%s;' % (arg.cname, Naming.optional_args_cname, self.type.opt_arg_cname(declarator.name))) Naming.pyrex_prefix, i))
declarator = arg.declarator
while not hasattr(declarator, 'name'):
declarator = declarator.base
code.putln('%s = %s->%s;' %
(arg.cname, Naming.optional_args_cname,
self.type.opt_arg_cname(declarator.name)))
used += 1
i += 1 i += 1
for _ in range(self.type.optional_arg_count): for _ in range(used):
code.putln('}') code.putln('}')
code.putln('}') code.putln('}')
...@@ -2321,8 +2344,12 @@ class DefNode(FuncDefNode): ...@@ -2321,8 +2344,12 @@ class DefNode(FuncDefNode):
if arg.is_self_arg or arg.is_type_arg: if arg.is_self_arg or arg.is_type_arg:
arg_code_list.append("PyObject *%s" % arg.hdr_cname) arg_code_list.append("PyObject *%s" % arg.hdr_cname)
else: else:
arg_code_list.append( decl = arg.hdr_type.declaration_code(arg.hdr_cname)
arg.hdr_type.declaration_code(arg.hdr_cname)) entry = self.local_scope.lookup(arg.name)
if not entry.cf_used:
arg_code_list.append('CYTHON_UNUSED ' + decl)
else:
arg_code_list.append(decl)
if not self.entry.is_special and sig.method_flags() == [TypeSlots.method_noargs]: if not self.entry.is_special and sig.method_flags() == [TypeSlots.method_noargs]:
arg_code_list.append("CYTHON_UNUSED PyObject *unused") arg_code_list.append("CYTHON_UNUSED PyObject *unused")
if (self.entry.scope.is_c_class_scope and self.entry.name == "__ipow__"): if (self.entry.scope.is_c_class_scope and self.entry.name == "__ipow__"):
......
...@@ -127,6 +127,7 @@ class Entry(object): ...@@ -127,6 +127,7 @@ class Entry(object):
# Currently only supported for CythonScope entries. # Currently only supported for CythonScope entries.
# error_on_uninitialized Have Control Flow issue an error when this entry is # error_on_uninitialized Have Control Flow issue an error when this entry is
# used uninitialized # used uninitialized
# cf_used boolean Entry is used
inline_func_in_pxd = False inline_func_in_pxd = False
borrowed = 0 borrowed = 0
...@@ -182,6 +183,7 @@ class Entry(object): ...@@ -182,6 +183,7 @@ class Entry(object):
in_with_gil_block = 0 in_with_gil_block = 0
from_cython_utility_code = None from_cython_utility_code = None
error_on_uninitialized = False error_on_uninitialized = False
cf_used = True
def __init__(self, name, cname, type, pos = None, init = None): def __init__(self, name, cname, type, pos = None, init = None):
self.name = name self.name = name
......
...@@ -35,6 +35,9 @@ def unused_and_unassigned(): ...@@ -35,6 +35,9 @@ def unused_and_unassigned():
cdef object foo cdef object foo
cdef int i cdef int i
def unused_generic(*args, **kwargs):
pass
_ERRORS = """ _ERRORS = """
6:6: Unused entry 'a' 6:6: Unused entry 'a'
9:9: Unused entry 'b' 9:9: Unused entry 'b'
...@@ -44,4 +47,6 @@ _ERRORS = """ ...@@ -44,4 +47,6 @@ _ERRORS = """
25:4: Unused entry 'Unused' 25:4: Unused entry 'Unused'
35:16: Unused entry 'foo' 35:16: Unused entry 'foo'
36:13: Unused entry 'i' 36:13: Unused entry 'i'
38:20: Unused argument 'args'
38:28: Unused argument 'kwargs'
""" """
cdef c_unused_simple(a, b, c):
"""
>>> c_unused_simple(1, 2, 3)
3
"""
return a + b
cdef c_unused_optional(a, b, c=1, d=2):
"""
>>> c_unused_optional(1, 2)
4
>>> c_unused_optional(1, 2, 3, 4)
6
"""
return b + d
cpdef cp_unused_simple(a, b, c):
"""
>>> cp_unused_simple(1, 2, 3)
3
"""
return a + b
cpdef cp_unused_optional(a, b, c=1, d=2):
"""
>>> cp_unused_optional(1, 2)
4
>>> cp_unused_optional(1, 2, 3, 4)
6
"""
return b + d
cdef class Unused:
"""
>>> o = Unused()
"""
cpdef cp_unused_simple(self, a, b, c):
return c
cpdef cp_unused_optional(self, a, b, c=1, d=2):
return b + d
cdef c_unused_simple(a, b, c):
"""
>>> c_unused_simple(1, 2, 3)
3
"""
return a + b
cdef c_unused_optional(a, b, c=1, d=2):
"""
>>> c_unused_optional(1, 2)
4
>>> c_unused_optional(1, 2, 3, 4)
6
"""
return b + d
cpdef cp_unused_simple(a, b, c):
"""
>>> cp_unused_simple(1, 2, 3)
3
"""
return a + b
cpdef cp_unused_optional(a, b, c=1, d=2):
"""
>>> cp_unused_optional(1, 2)
4
>>> cp_unused_optional(1, 2, 3, 4)
6
"""
return b + d
cdef class Unused:
"""
>>> o = Unused()
"""
cpdef cp_unused_simple(self, a, b, c):
return c
cpdef cp_unused_optional(self, a, b, c=1, d=2):
return b + d
def def_unused(a, b, c):
"""
>>> def_unused(1, 2, 3)
"""
def def_unused_metho(o):
"""
>>> def_unused_metho(0)
"""
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment