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):
return
if storage_class:
self.put("%s " % storage_class)
if not entry.cf_used:
self.put('CYTHON_UNUSED ')
self.put(entry.type.declaration_code(
entry.cname, dll_linkage = dll_linkage))
if entry.init is not None:
......
import cython
cython.declare(PyrexTypes=object, Naming=object, ExprNodes=object, Nodes=object,
Options=object, UtilNodes=object, ModuleNode=object,
......@@ -145,7 +144,8 @@ class ControlFlow(object):
if entry.type.is_array or entry.type.is_struct_or_union:
return False
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):
"""Mark position, will be used to draw graph nodes."""
......@@ -501,18 +501,21 @@ def check_definitions(flow, compiler_directives):
# Unused result
for assmt in assignments:
if not assmt.refs and not assmt.entry.is_pyclass_attr \
and not assmt.entry.in_closure:
if (not assmt.refs and not assmt.entry.is_pyclass_attr
and not assmt.entry.in_closure):
if assmt.entry.cf_references and warn_unused_result:
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:
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
# Unused 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
for assmt in entry.cf_assignments:
if assmt.is_arg:
......@@ -522,13 +525,13 @@ def check_definitions(flow, compiler_directives):
is_arg = False
if is_arg:
if warn_unused_arg:
messages.warning(entry.pos, "Unused argument '%s'" % entry.name)
# TODO: handle unused arguments
entry.cf_used = True
messages.warning(entry.pos, "Unused argument '%s'" %
entry.name)
else:
if warn_unused:
messages.warning(entry.pos, "Unused entry '%s'" % entry.name)
entry.cf_used = False
messages.warning(entry.pos, "Unused entry '%s'" %
entry.name)
entry.cf_used = False
messages.report()
......@@ -711,7 +714,9 @@ class CreateControlFlowGraph(CythonTransform):
if arg.is_name:
entry = arg.entry or self.env.lookup(arg.name)
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
self.visit(arg)
self.flow.mark_deletion(arg, entry)
......@@ -1096,7 +1101,8 @@ class CreateControlFlowGraph(CythonTransform):
self.flow.mark_assignment(node.target,
object_expr, self.env.lookup(node.name))
# 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 = node.scope
self.flow.nextblock()
......
......@@ -1670,6 +1670,7 @@ class CFuncDefNode(FuncDefNode):
inline_in_pxd = False
decorators = None
directive_locals = None
override = None
def unqualified_name(self):
return self.entry.name
......@@ -1792,12 +1793,22 @@ class CFuncDefNode(FuncDefNode):
return False
def generate_function_header(self, code, with_pymethdef, with_opt_args = 1, with_dispatch = 1, cname = None):
scope = self.local_scope
arg_decls = []
type = self.type
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:
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:
arg_decls.append(type.op_arg_struct.declaration_code(Naming.optional_args_cname))
if type.has_varargs:
......@@ -1823,28 +1834,40 @@ class CFuncDefNode(FuncDefNode):
code.putln("%s%s%s {" % (storage_class, modifiers, header))
def generate_argument_declarations(self, env, code):
scope = self.local_scope
for arg in self.args:
if arg.default:
result = arg.calculate_default_value_code(code)
code.putln('%s = %s;' % (
arg.type.declaration_code(arg.cname), result))
entry = scope.lookup(arg.name)
if self.override or entry.cf_used:
result = arg.calculate_default_value_code(code)
code.putln('%s = %s;' % (
arg.type.declaration_code(arg.cname), result))
def generate_keyword_list(self, code):
pass
def generate_argument_parsing_code(self, env, code):
i = 0
used = 0
if self.type.optional_arg_count:
scope = self.local_scope
code.putln('if (%s) {' % Naming.optional_args_cname)
for arg in self.args:
if arg.default:
code.putln('if (%s->%sn > %s) {' % (Naming.optional_args_cname, 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)))
entry = scope.lookup(arg.name)
if self.override or entry.cf_used:
code.putln('if (%s->%sn > %s) {' %
(Naming.optional_args_cname,
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
for _ in range(self.type.optional_arg_count):
for _ in range(used):
code.putln('}')
code.putln('}')
......@@ -2321,8 +2344,12 @@ class DefNode(FuncDefNode):
if arg.is_self_arg or arg.is_type_arg:
arg_code_list.append("PyObject *%s" % arg.hdr_cname)
else:
arg_code_list.append(
arg.hdr_type.declaration_code(arg.hdr_cname))
decl = 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]:
arg_code_list.append("CYTHON_UNUSED PyObject *unused")
if (self.entry.scope.is_c_class_scope and self.entry.name == "__ipow__"):
......
......@@ -127,6 +127,7 @@ class Entry(object):
# Currently only supported for CythonScope entries.
# error_on_uninitialized Have Control Flow issue an error when this entry is
# used uninitialized
# cf_used boolean Entry is used
inline_func_in_pxd = False
borrowed = 0
......@@ -182,6 +183,7 @@ class Entry(object):
in_with_gil_block = 0
from_cython_utility_code = None
error_on_uninitialized = False
cf_used = True
def __init__(self, name, cname, type, pos = None, init = None):
self.name = name
......
......@@ -35,6 +35,9 @@ def unused_and_unassigned():
cdef object foo
cdef int i
def unused_generic(*args, **kwargs):
pass
_ERRORS = """
6:6: Unused entry 'a'
9:9: Unused entry 'b'
......@@ -44,4 +47,6 @@ _ERRORS = """
25:4: Unused entry 'Unused'
35:16: Unused entry 'foo'
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