def get_all_PyMethodDef_initializers(): """ Locate all initializers for PyMethodDef, returning a list of StructInitializer instances """ log('get_all_PyMethodDef_initializers') result = [] vars = gcc.get_variables() for var in vars: if isinstance(var.decl, gcc.VarDecl): if isinstance(var.decl.type, gcc.ArrayType): if str(var.decl.type.type) == 'struct PyMethodDef': if var.decl.initial: table = [] for idx, ctor in var.decl.initial.elements: #print idx, ctor si = PyMethodDefInitializer(ctor) table.append(si) # Warn about missing sentinel entry with # ml->ml_name == NULL ml_name = table[-1].char_ptr_field('ml_name') if 0: print('final ml_name: %r' % ml_name) if ml_name is not None: gcc.warning(table[-1].get_location(), 'missing NULL sentinel value at end of PyMethodDef table') result += table return result
def get_all_PyMethodDef_initializers(): """ Locate all initializers for PyMethodDef, returning a list of StructInitializer instances """ log('get_all_PyMethodDef_initializers') result = [] vars = gcc.get_variables() for var in vars: if isinstance(var.decl, gcc.VarDecl): if isinstance(var.decl.type, gcc.ArrayType): if str(var.decl.type.type) == 'struct PyMethodDef': if var.decl.initial: table = [] for idx, ctor in var.decl.initial.elements: #print idx, ctor si = PyMethodDefInitializer(ctor) table.append(si) # Warn about missing sentinel entry with # ml->ml_name == NULL ml_name = table[-1].char_ptr_field('ml_name') if 0: print('final ml_name: %r' % ml_name) if ml_name is not None: gcc.warning( table[-1].get_location(), 'missing NULL sentinel value at end of PyMethodDef table' ) result += table return result
def verify_any_PyMethodDef_flags(): """ Check all initializers for PyMethodDef arrays. Verify that the flags used match the real signature of the callback function (albeit usually cast to a PyCFunction): http://docs.python.org/c-api/structures.html#PyMethodDef """ methods = get_all_PyMethodDef_initializers() #from pprint import pprint #pprint(methods) for si in methods: if 0: print(si) ml_meth = si.function_ptr_field('ml_meth') ml_flags = si.int_field('ml_flags') if 0: print(' ml_meth: %r' % ml_meth) print(' ml_flags: %r' % ml_flags) check_isinstance(ml_flags, int) if ml_meth is not None: check_isinstance(ml_meth, gcc.FunctionDecl) if ml_flags & METH_KEYWORDS: expargs = 3 exptypemsg = 'expected ml_meth callback of type "PyObject (fn)(someobject *, PyObject *args, PyObject *kwargs)" due to METH_KEYWORDS flag' else: expargs = 2 exptypemsg = 'expected ml_meth callback of type "PyObject (fn)(someobject *, PyObject *)"' actualargs = len(ml_meth.type.argument_types) if expargs != actualargs: gcc.warning( si.get_location(), 'flags do not match callback signature for %r' ' within PyMethodDef table' % ml_meth.name) gcc.inform(si.get_location(), exptypemsg + ' (%s arguments)' % expargs) gcc.inform( si.get_location(), 'actual type of underlying callback: %s' % ml_meth.type + ' (%s arguments)' % actualargs) gcc.inform( si.get_location(), 'see http://docs.python.org/c-api/structures.html#PyMethodDef' )
def verify_any_PyMethodDef_flags(): """ Check all initializers for PyMethodDef arrays. Verify that the flags used match the real signature of the callback function (albeit usually cast to a PyCFunction): http://docs.python.org/c-api/structures.html#PyMethodDef """ methods = get_all_PyMethodDef_initializers() #from pprint import pprint #pprint(methods) for si in methods: if 0: print(si) ml_meth = si.function_ptr_field('ml_meth') ml_flags = si.int_field('ml_flags') if 0: print(' ml_meth: %r' % ml_meth) print(' ml_flags: %r' % ml_flags) check_isinstance(ml_flags, int) if ml_meth is not None: check_isinstance(ml_meth, gcc.FunctionDecl) if ml_flags & METH_KEYWORDS: expargs = 3 exptypemsg = 'expected ml_meth callback of type "PyObject (fn)(someobject *, PyObject *args, PyObject *kwargs)" due to METH_KEYWORDS flag' else: expargs = 2 exptypemsg = 'expected ml_meth callback of type "PyObject (fn)(someobject *, PyObject *)"' actualargs = len(ml_meth.type.argument_types) if expargs != actualargs: gcc.warning(si.get_location(), 'flags do not match callback signature for %r' ' within PyMethodDef table' % ml_meth.name) gcc.inform(si.get_location(), exptypemsg + ' (%s arguments)' % expargs) gcc.inform(si.get_location(), 'actual type of underlying callback: %s' % ml_meth.type + ' (%s arguments)' % actualargs) gcc.inform(si.get_location(), 'see http://docs.python.org/c-api/structures.html#PyMethodDef')
def spellcheck_node(self, node, loc): # Spellcheck any textual constants found within the node: if isinstance(node, gcc.StringCst): words = node.constant.split() for word in words: if not spellingdict.check(word): # Warn about the spelling error (controlling the warning # with the -Wall command-line option): if gcc.warning(loc, 'Possibly misspelt word in string constant: %r' % word, gcc.Option('-Wall')): # and, if the warning was not suppressed at the command line, emit # suggested respellings: suggestions = spellingdict.suggest(word) if suggestions: gcc.inform(loc, 'Suggested respellings: %r' % ', '.join(suggestions))
def on_pass_execution(p, fn): if p.name == '*warn_function_return': gcc.error(fn.start, 'this is an error (with positional args)') gcc.error(location=fn.start, message='this is an error (with keyword args)') gcc.warning(fn.end, 'this is a warning (with positional args)', gcc.Option('-Wdiv-by-zero')) gcc.warning(location=fn.end, message='this is a warning (with keyword args)', option=gcc.Option('-Wdiv-by-zero')) gcc.error( fn.start, # These should be passed through, without triggering errors: 'a warning with some embedded format strings %s and %i') # Verify that -Wno-format was honored # The behavior of these flags changed in 4.8, so skip this part # on gcc 4.8 onwards: if gcc.GCCPLUGINS_API_VERSION <= 4007: gcc.warning(fn.end, 'this warning ought not to appear', gcc.Option('-Wformat')) # Verify that we can issue an unconditional warning, with no option # (as per https://fedorahosted.org/gcc-python-plugin/ticket/8 ): gcc.warning(fn.end, 'this is an unconditional warning') gcc.warning(fn.end, 'this is another unconditional warning', None) # Verify that gcc.warning handles an object of the wrong type by # raising a TypeError try: gcc.warning( fn.end, 'this is another unconditional warning', 'this should have been a gcc.Option instance, or None') except TypeError: err = sys.exc_info()[1] sys.stderr.write('expected error was found: %s\n' % err) else: raise RuntimeError('expected exception was not raised') # Exercise gcc.inform: gcc.inform(fn.start, 'This is the start of the function') gcc.inform(fn.end, 'This is the end of the function')
def flush(self): gcc.warning(self.loc, self.msg)
def on_pass_execution(p, fn): if p.name == '*warn_function_return': gcc.error(fn.start, 'this is an error (with positional args)') gcc.error(location=fn.start, message='this is an error (with keyword args)') gcc.warning(fn.end, 'this is a warning (with positional args)', gcc.Option('-Wdiv-by-zero')) gcc.warning(location=fn.end, message='this is a warning (with keyword args)', option=gcc.Option('-Wdiv-by-zero')) gcc.error(fn.start, # These should be passed through, without triggering errors: 'a warning with some embedded format strings %s and %i') # Verify that -Wno-format was honored # The behavior of these flags changed in 4.8, so skip this part # on gcc 4.8 onwards: if gcc.GCCPLUGINS_API_VERSION <= 4007: gcc.warning(fn.end, 'this warning ought not to appear', gcc.Option('-Wformat')) # Verify that we can issue an unconditional warning, with no option # (as per https://fedorahosted.org/gcc-python-plugin/ticket/8 ): gcc.warning(fn.end, 'this is an unconditional warning') gcc.warning(fn.end, 'this is another unconditional warning', None) # Verify that gcc.warning handles an object of the wrong type by # raising a TypeError try: gcc.warning(fn.end, 'this is another unconditional warning', 'this should have been a gcc.Option instance, or None') except TypeError: err = sys.exc_info()[1] sys.stderr.write('expected error was found: %s\n' % err) else: raise RuntimeError('expected exception was not raised') # Exercise gcc.inform: gcc.inform(fn.start, 'This is the start of the function') gcc.inform(fn.end, 'This is the end of the function')