[gcc-python-plugin] run-test-suite.py: type IDs are hexadecimal
by David Hugh Malcolm
commit 48e0e4184f6e749f529ca9674a803084817f5a51
Author: David Narvaez <david.narvaez(a)computer.org>
Date: Tue Jan 3 19:11:21 2012 -0500
run-test-suite.py: type IDs are hexadecimal
Fix the scrubber for internal type IDs within run-test-suite.py so that it
works on hexadecimal digits, rather than just decimal digits
The strings in question appear to be generated from an invocation like this:
pp_printf (buffer, "<T%x>", TYPE_UID (node));
within gcc/tree-pretty-print.c,
and looking in gcc/pretty-print.c, format code 'x' appears to be hexadecimal:
pp_scalar (pp, HOST_WIDE_INT_PRINT_HEX,
run-test-suite.py | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
---
diff --git a/run-test-suite.py b/run-test-suite.py
index 9415e1d..50eaae1 100644
--- a/run-test-suite.py
+++ b/run-test-suite.py
@@ -109,7 +109,7 @@ class TestStream:
# Remove exact numbers from types
# (e.g. from "int (*<T513>) (int)" to "int (*<Tnnn>) (int)"):
- line = re.sub('<T([0-9]+)>', '<Tnnn>', line)
+ line = re.sub('<T([0-9a-f]+)>', '<Tnnn>', line)
# Remove exact path to Python header file and line number
# e.g.
12 years, 5 months
[gcc-python-plugin] cpychecker: convert format string checker from permerror to warning
by David Hugh Malcolm
commit 79e8350b07ed99b5fb01584249e5ee3fbafcbed8
Author: David Malcolm <dmalcolm(a)redhat.com>
Date: Tue Jan 3 17:56:02 2012 -0500
cpychecker: convert format string checker from permerror to warning
Convert messages about format string problems from using gcc.permerror() to
using gcc.warning()
libcpychecker/formatstrings.py | 38 ++++++++++----------
libcpychecker/refcounts.py | 2 +-
testcpychecker.py | 16 ++++----
.../incorrect_codes_S_and_U/metadata.ini | 3 ++
.../PyArg_Parse/incorrect_codes_S_and_U/stderr.txt | 4 +-
.../PyArg_ParseTuple/code_O_bang/metadata.ini | 3 ++
.../PyArg_ParseTuple/code_O_bang/stderr.txt | 6 ++--
.../code_s/incorrect-constness/metadata.ini | 3 ++
.../code_s/incorrect-constness/stderr.txt | 2 +-
.../incorrect_code_z_hash/metadata.ini | 3 ++
.../incorrect_code_z_hash/stderr.txt | 2 +-
.../incorrect_codes_S_and_U/metadata.ini | 3 ++
.../incorrect_codes_S_and_U/stderr.txt | 4 +-
.../incorrect_converters/metadata.ini | 3 ++
.../incorrect_converters/stderr.txt | 24 ++++++------
.../PyArg_ParseTuple/keywords/metadata.ini | 3 ++
.../PyArg_ParseTuple/keywords/stderr.txt | 2 +-
.../with_PY_SSIZE_T_CLEAN/metadata.ini | 3 ++
.../with_PY_SSIZE_T_CLEAN/stderr.txt | 16 ++++----
.../without_PY_SSIZE_T_CLEAN/metadata.ini | 3 ++
.../without_PY_SSIZE_T_CLEAN/stderr.txt | 16 ++++----
21 files changed, 93 insertions(+), 66 deletions(-)
---
diff --git a/libcpychecker/formatstrings.py b/libcpychecker/formatstrings.py
index b116a9b..a49fce8 100644
--- a/libcpychecker/formatstrings.py
+++ b/libcpychecker/formatstrings.py
@@ -50,17 +50,17 @@ class NullPointer:
def describe(self):
return 'NULL'
-class CExtensionError(Exception):
- # Base class for errors discovered by static analysis in C extension code
+class CExtensionWarning(Exception):
+ # Base class for warnings discovered by static analysis in C extension code
pass
-class FormatStringError(CExtensionError):
+class FormatStringWarning(CExtensionWarning):
def __init__(self, fmt_string):
self.fmt_string = fmt_string
-class UnknownFormatChar(FormatStringError):
+class UnknownFormatChar(FormatStringWarning):
def __init__(self, fmt_string, ch):
- FormatStringError.__init__(self, fmt_string)
+ FormatStringWarning.__init__(self, fmt_string)
self.ch = ch
def __str__(self):
@@ -71,13 +71,13 @@ class UnhandledCode(UnknownFormatChar):
return "unhandled format code in \"%s\": '%s' (FIXME)" % (self.fmt_string, self.ch)
-class MismatchedParentheses(FormatStringError):
+class MismatchedParentheses(FormatStringWarning):
def __str__(self):
return "mismatched parentheses in format string \"%s\"" % (self.fmt_string, )
-class ParsedFormatStringError(FormatStringError):
+class ParsedFormatStringWarning(FormatStringWarning):
def __init__(self, funcname, fmt):
- FormatStringError.__init__(self, fmt.fmt_string)
+ FormatStringWarning.__init__(self, fmt.fmt_string)
self.funcname = funcname
self.fmt = fmt
@@ -131,9 +131,9 @@ class ParsedFormatString:
return ('%s(fmt_string=%r, args=%r)'
% (self.__class__.__name__, self.fmt_string, self.args))
-class WrongNumberOfVars(ParsedFormatStringError):
+class WrongNumberOfVars(ParsedFormatStringWarning):
def __init__(self, funcname, fmt, varargs):
- ParsedFormatStringError.__init__(self, funcname, fmt)
+ ParsedFormatStringWarning.__init__(self, funcname, fmt)
self.varargs = varargs
def __str__(self):
@@ -164,7 +164,7 @@ class TooManyVars(WrongNumberOfVars):
def _get_desc_prefix(self):
return 'Too many arguments'
-class MismatchingType(ParsedFormatStringError):
+class MismatchingType(ParsedFormatStringWarning):
def __init__(self, funcname, fmt, arg_num, arg_fmt_string, exp_type, vararg):
super(self.__class__, self).__init__(funcname, fmt)
self.arg_num = arg_num
@@ -348,11 +348,11 @@ def check_pyargs(fun):
elif isinstance(contents, gcc.IntegerCst):
elements[elt_idx] = contents.constant
if elements[-1] != 0:
- gcc.permerror(stmt.loc, 'keywords to PyArg_ParseTupleAndKeywords are not NULL-terminated')
+ gcc.warning(stmt.loc, 'keywords to PyArg_ParseTupleAndKeywords are not NULL-terminated')
i = 0
for elt in elements[0:-1]:
if not elt:
- gcc.permerror(stmt.loc, 'keyword argument %d missing in PyArg_ParseTupleAndKeywords call' % i)
+ gcc.warning(stmt.loc, 'keyword argument %d missing in PyArg_ParseTupleAndKeywords call' % i)
i = i + 1
def check_callsite(stmt, parser, funcname, format_idx, varargs_idx, with_size_t):
@@ -379,9 +379,9 @@ def check_pyargs(fun):
# Figure out expected types, based on the format string...
try:
fmt = parser.from_string(fmt_string, with_size_t)
- except FormatStringError:
+ except FormatStringWarning:
exc = sys.exc_info()[1]
- gcc.permerror(stmt.loc, str(exc))
+ gcc.warning(stmt.loc, str(exc))
return
log('fmt: %r', fmt.args)
@@ -392,11 +392,11 @@ def check_pyargs(fun):
varargs = stmt.args[varargs_idx:]
# log('varargs: %r', varargs)
if len(varargs) < len(exp_types):
- gcc.permerror(loc, str(NotEnoughVars(funcname, fmt, varargs)))
+ gcc.warning(loc, str(NotEnoughVars(funcname, fmt, varargs)))
return
if len(varargs) > len(exp_types):
- gcc.permerror(loc, str(TooManyVars(funcname, fmt, varargs)))
+ gcc.warning(loc, str(TooManyVars(funcname, fmt, varargs)))
return
for index, ((exp_arg, exp_type), vararg) in enumerate(zip(exp_types, varargs)):
@@ -408,8 +408,8 @@ def check_pyargs(fun):
loc = vararg.location
else:
loc = stmt.loc
- gcc.permerror(loc,
- str(err))
+ gcc.warning(loc,
+ str(err))
sys.stderr.write(err.extra_info())
def maybe_check_callsite(stmt):
diff --git a/libcpychecker/refcounts.py b/libcpychecker/refcounts.py
index 78e9660..a3dd830 100644
--- a/libcpychecker/refcounts.py
+++ b/libcpychecker/refcounts.py
@@ -29,7 +29,7 @@ from libcpychecker.absinterp import *
from libcpychecker.attributes import fnnames_returning_borrowed_refs, \
stolen_refs_by_fnname
from libcpychecker.diagnostics import Reporter, Annotator, Note
-from libcpychecker.PyArg_ParseTuple import PyArgParseFmt, FormatStringError, \
+from libcpychecker.PyArg_ParseTuple import PyArgParseFmt, FormatStringWarning,\
TypeCheckCheckerType, TypeCheckResultType, \
ConverterCallbackType, ConverterResultType
from libcpychecker.Py_BuildValue import PyBuildValueFmt, ObjectFormatUnit, \
diff --git a/testcpychecker.py b/testcpychecker.py
index 0dfa1da..22b9ebb 100644
--- a/testcpychecker.py
+++ b/testcpychecker.py
@@ -101,7 +101,7 @@ class PyArg_ParseTupleTests(AnalyzerTests):
' Py_RETURN_NONE;\n'
'}\n')
experr = ("$(SRCFILE): In function 'bogus_format_string':\n"
- '$(SRCFILE):12:26: error: unknown format char in "This is not a valid format string": \'T\' [-fpermissive]\n')
+ '$(SRCFILE):12:26: error: unknown format char in "This is not a valid format string": \'T\' [-Werror]\n')
self.assertFindsError(src, experr)
def test_finding_htons_error(self):
@@ -133,7 +133,7 @@ socket_htons(PyObject *self, PyObject *args)
"""
self.assertFindsError(src,
"$(SRCFILE): In function 'socket_htons':\n"
- '$(SRCFILE):17:26: error: Mismatching type in call to PyArg_ParseTuple with format code "i:htons" [-fpermissive]\n'
+ '$(SRCFILE):17:26: error: Mismatching type in call to PyArg_ParseTuple with format code "i:htons" [-Werror]\n'
' argument 3 ("&x1") had type\n'
' "long unsigned int *" (pointing to 64 bits)\n'
' but was expecting\n'
@@ -157,7 +157,7 @@ not_enough_varargs(PyObject *self, PyObject *args)
' expected 1 extra arguments:\n'
' "int *" (pointing to 32 bits)\n'
' but got none\n'
- ' [-fpermissive]\n')
+ ' [-Werror]\n')
def test_too_many_varargs(self):
src = """
@@ -179,7 +179,7 @@ too_many_varargs(PyObject *self, PyObject *args)
' but got 2:\n'
' "int *" (pointing to 32 bits)\n'
' "int *" (pointing to 32 bits)\n'
- ' [-fpermissive]\n')
+ ' [-Werror]\n')
def test_correct_usage(self):
src = """
@@ -249,7 +249,7 @@ correct_usage(PyObject *self, PyObject *args)
def get_expected_error(self):
return ("$(SRCFILE): In function '%(function_name)s':\n"
- '$(SRCFILE):%(linenum)i:%(colnum)i: error: Mismatching type in call to %(funcname)s with format code "%(code)s" [-fpermissive]\n'
+ '$(SRCFILE):%(linenum)i:%(colnum)i: error: Mismatching type in call to %(funcname)s with format code "%(code)s" [-Werror]\n'
' argument %(argindex)i ("&val") had type\n'
' "void * *"\n'
' but was expecting\n'
@@ -482,7 +482,7 @@ class Py_BuildValueTests(AnalyzerTests):
' return Py_BuildValue("this is not a valid format string");\n'
'}\n')
experr = ("$(SRCFILE): In function 'bogus_format_string':\n"
- '$(SRCFILE):12:5: error: unknown format char in "this is not a valid format string": \'t\' [-fpermissive]\n')
+ '$(SRCFILE):12:5: error: unknown format char in "this is not a valid format string": \'t\' [-Werror]\n')
self.assertFindsError(src, experr)
def test_not_enough_varargs(self):
@@ -499,7 +499,7 @@ not_enough_varargs(PyObject *self, PyObject *args)
' expected 1 extra arguments:\n'
' "int"\n'
' but got none\n'
- ' [-fpermissive]\n')
+ ' [-Werror]\n')
def test_too_many_varargs(self):
src = """
@@ -517,7 +517,7 @@ too_many_varargs(PyObject *self, PyObject *args)
' but got 2:\n'
' "int"\n'
' "int"\n'
- ' [-fpermissive]\n')
+ ' [-Werror]\n')
def test_correct_usage(self):
src = """
diff --git a/tests/cpychecker/PyArg_Parse/incorrect_codes_S_and_U/metadata.ini b/tests/cpychecker/PyArg_Parse/incorrect_codes_S_and_U/metadata.ini
new file mode 100644
index 0000000..0d5711c
--- /dev/null
+++ b/tests/cpychecker/PyArg_Parse/incorrect_codes_S_and_U/metadata.ini
@@ -0,0 +1,3 @@
+[ExpectedBehavior]
+# We expect only compilation *warnings*, so we expect a 0 exit code
+exitcode = 0
diff --git a/tests/cpychecker/PyArg_Parse/incorrect_codes_S_and_U/stderr.txt b/tests/cpychecker/PyArg_Parse/incorrect_codes_S_and_U/stderr.txt
index fc82029..0b97aaf 100644
--- a/tests/cpychecker/PyArg_Parse/incorrect_codes_S_and_U/stderr.txt
+++ b/tests/cpychecker/PyArg_Parse/incorrect_codes_S_and_U/stderr.txt
@@ -1,11 +1,11 @@
tests/cpychecker/PyArg_Parse/incorrect_codes_S_and_U/input.c: In function 'incorrect_usage_of_S_and_U':
-tests/cpychecker/PyArg_Parse/incorrect_codes_S_and_U/input.c:33:21: error: Mismatching type in call to PyArg_Parse with format code "SU" [-fpermissive]
+tests/cpychecker/PyArg_Parse/incorrect_codes_S_and_U/input.c:33:21: warning: Mismatching type in call to PyArg_Parse with format code "SU" [enabled by default]
argument 3 ("&val1") had type
"int *" (pointing to 32 bits)
but was expecting
one of "struct PyStringObject * *" or "struct PyObject * *"
for format code "S"
-tests/cpychecker/PyArg_Parse/incorrect_codes_S_and_U/input.c:33:21: error: Mismatching type in call to PyArg_Parse with format code "SU" [-fpermissive]
+tests/cpychecker/PyArg_Parse/incorrect_codes_S_and_U/input.c:33:21: warning: Mismatching type in call to PyArg_Parse with format code "SU" [enabled by default]
argument 4 ("&val2") had type
"int *" (pointing to 32 bits)
but was expecting
diff --git a/tests/cpychecker/PyArg_ParseTuple/code_O_bang/metadata.ini b/tests/cpychecker/PyArg_ParseTuple/code_O_bang/metadata.ini
new file mode 100644
index 0000000..0d5711c
--- /dev/null
+++ b/tests/cpychecker/PyArg_ParseTuple/code_O_bang/metadata.ini
@@ -0,0 +1,3 @@
+[ExpectedBehavior]
+# We expect only compilation *warnings*, so we expect a 0 exit code
+exitcode = 0
diff --git a/tests/cpychecker/PyArg_ParseTuple/code_O_bang/stderr.txt b/tests/cpychecker/PyArg_ParseTuple/code_O_bang/stderr.txt
index a19f179..bffd418 100644
--- a/tests/cpychecker/PyArg_ParseTuple/code_O_bang/stderr.txt
+++ b/tests/cpychecker/PyArg_ParseTuple/code_O_bang/stderr.txt
@@ -1,17 +1,17 @@
tests/cpychecker/PyArg_ParseTuple/code_O_bang/input.c: In function 'handle_subclasses':
-tests/cpychecker/PyArg_ParseTuple/code_O_bang/input.c:85:19: error: Mismatching type in call to PyArg_ParseTuple with format code "O!O!O!O!O!O!O!" [-fpermissive]
+tests/cpychecker/PyArg_ParseTuple/code_O_bang/input.c:85:19: warning: Mismatching type in call to PyArg_ParseTuple with format code "O!O!O!O!O!O!O!" [enabled by default]
argument 10 ("gcc.VarDecl('long_obj')") had type
"struct PyLongObject *"
but was expecting
"struct PyUnicodeObject * *" (based on PyTypeObject: 'PyUnicode_Type') or "struct PyObject * *"
for format code "O!"
-tests/cpychecker/PyArg_ParseTuple/code_O_bang/input.c:90:26: error: Mismatching type in call to PyArg_ParseTuple with format code "O!O!O!O!O!O!O!" [-fpermissive]
+tests/cpychecker/PyArg_ParseTuple/code_O_bang/input.c:90:26: warning: Mismatching type in call to PyArg_ParseTuple with format code "O!O!O!O!O!O!O!" [enabled by default]
argument 12 ("&unknown_obj") had type
"struct UnknownObject * *"
but was expecting
""struct PyObject * *"" (unable to determine relevant PyTypeObject)
for format code "O!"
-tests/cpychecker/PyArg_ParseTuple/code_O_bang/input.c:90:26: error: Mismatching type in call to PyArg_ParseTuple with format code "O!O!O!O!O!O!O!" [-fpermissive]
+tests/cpychecker/PyArg_ParseTuple/code_O_bang/input.c:90:26: warning: Mismatching type in call to PyArg_ParseTuple with format code "O!O!O!O!O!O!O!" [enabled by default]
argument 14 ("&extension_obj") had type
"struct ExtensionObject * *"
but was expecting
diff --git a/tests/cpychecker/PyArg_ParseTuple/code_s/incorrect-constness/metadata.ini b/tests/cpychecker/PyArg_ParseTuple/code_s/incorrect-constness/metadata.ini
new file mode 100644
index 0000000..0d5711c
--- /dev/null
+++ b/tests/cpychecker/PyArg_ParseTuple/code_s/incorrect-constness/metadata.ini
@@ -0,0 +1,3 @@
+[ExpectedBehavior]
+# We expect only compilation *warnings*, so we expect a 0 exit code
+exitcode = 0
diff --git a/tests/cpychecker/PyArg_ParseTuple/code_s/incorrect-constness/stderr.txt b/tests/cpychecker/PyArg_ParseTuple/code_s/incorrect-constness/stderr.txt
index 7aa7320..a1e7c05 100644
--- a/tests/cpychecker/PyArg_ParseTuple/code_s/incorrect-constness/stderr.txt
+++ b/tests/cpychecker/PyArg_ParseTuple/code_s/incorrect-constness/stderr.txt
@@ -1,5 +1,5 @@
tests/cpychecker/PyArg_ParseTuple/code_s/incorrect-constness/input.c: In function 'test':
-tests/cpychecker/PyArg_ParseTuple/code_s/incorrect-constness/input.c:34:26: error: Mismatching type in call to PyArg_ParseTuple with format code "s" [-fpermissive]
+tests/cpychecker/PyArg_ParseTuple/code_s/incorrect-constness/input.c:34:26: warning: Mismatching type in call to PyArg_ParseTuple with format code "s" [enabled by default]
argument 3 ("&str") had type
"char * *"
but was expecting
diff --git a/tests/cpychecker/PyArg_ParseTuple/incorrect_code_z_hash/metadata.ini b/tests/cpychecker/PyArg_ParseTuple/incorrect_code_z_hash/metadata.ini
new file mode 100644
index 0000000..0d5711c
--- /dev/null
+++ b/tests/cpychecker/PyArg_ParseTuple/incorrect_code_z_hash/metadata.ini
@@ -0,0 +1,3 @@
+[ExpectedBehavior]
+# We expect only compilation *warnings*, so we expect a 0 exit code
+exitcode = 0
diff --git a/tests/cpychecker/PyArg_ParseTuple/incorrect_code_z_hash/stderr.txt b/tests/cpychecker/PyArg_ParseTuple/incorrect_code_z_hash/stderr.txt
index d48e859..1f0b858 100644
--- a/tests/cpychecker/PyArg_ParseTuple/incorrect_code_z_hash/stderr.txt
+++ b/tests/cpychecker/PyArg_ParseTuple/incorrect_code_z_hash/stderr.txt
@@ -1,5 +1,5 @@
tests/cpychecker/PyArg_ParseTuple/incorrect_code_z_hash/input.c: In function 'incorrect_code_z_hash':
-tests/cpychecker/PyArg_ParseTuple/incorrect_code_z_hash/input.c:34:26: error: Mismatching type in call to PyArg_ParseTuple with format code "z#" [-fpermissive]
+tests/cpychecker/PyArg_ParseTuple/incorrect_code_z_hash/input.c:34:26: warning: Mismatching type in call to PyArg_ParseTuple with format code "z#" [enabled by default]
argument 4 ("&len") had type
"float *" (pointing to 32 bits)
but was expecting
diff --git a/tests/cpychecker/PyArg_ParseTuple/incorrect_codes_S_and_U/metadata.ini b/tests/cpychecker/PyArg_ParseTuple/incorrect_codes_S_and_U/metadata.ini
new file mode 100644
index 0000000..0d5711c
--- /dev/null
+++ b/tests/cpychecker/PyArg_ParseTuple/incorrect_codes_S_and_U/metadata.ini
@@ -0,0 +1,3 @@
+[ExpectedBehavior]
+# We expect only compilation *warnings*, so we expect a 0 exit code
+exitcode = 0
diff --git a/tests/cpychecker/PyArg_ParseTuple/incorrect_codes_S_and_U/stderr.txt b/tests/cpychecker/PyArg_ParseTuple/incorrect_codes_S_and_U/stderr.txt
index 7c44394..63f93fa 100644
--- a/tests/cpychecker/PyArg_ParseTuple/incorrect_codes_S_and_U/stderr.txt
+++ b/tests/cpychecker/PyArg_ParseTuple/incorrect_codes_S_and_U/stderr.txt
@@ -1,11 +1,11 @@
tests/cpychecker/PyArg_ParseTuple/incorrect_codes_S_and_U/input.c: In function 'incorrect_usage_of_S_and_U':
-tests/cpychecker/PyArg_ParseTuple/incorrect_codes_S_and_U/input.c:29:26: error: Mismatching type in call to PyArg_ParseTuple with format code "SU" [-fpermissive]
+tests/cpychecker/PyArg_ParseTuple/incorrect_codes_S_and_U/input.c:29:26: warning: Mismatching type in call to PyArg_ParseTuple with format code "SU" [enabled by default]
argument 3 ("&val1") had type
"int *" (pointing to 32 bits)
but was expecting
one of "struct PyStringObject * *" or "struct PyObject * *"
for format code "S"
-tests/cpychecker/PyArg_ParseTuple/incorrect_codes_S_and_U/input.c:29:26: error: Mismatching type in call to PyArg_ParseTuple with format code "SU" [-fpermissive]
+tests/cpychecker/PyArg_ParseTuple/incorrect_codes_S_and_U/input.c:29:26: warning: Mismatching type in call to PyArg_ParseTuple with format code "SU" [enabled by default]
argument 4 ("&val2") had type
"int *" (pointing to 32 bits)
but was expecting
diff --git a/tests/cpychecker/PyArg_ParseTuple/incorrect_converters/metadata.ini b/tests/cpychecker/PyArg_ParseTuple/incorrect_converters/metadata.ini
new file mode 100644
index 0000000..0d5711c
--- /dev/null
+++ b/tests/cpychecker/PyArg_ParseTuple/incorrect_converters/metadata.ini
@@ -0,0 +1,3 @@
+[ExpectedBehavior]
+# We expect only compilation *warnings*, so we expect a 0 exit code
+exitcode = 0
diff --git a/tests/cpychecker/PyArg_ParseTuple/incorrect_converters/stderr.txt b/tests/cpychecker/PyArg_ParseTuple/incorrect_converters/stderr.txt
index 76fc47a..a117994 100644
--- a/tests/cpychecker/PyArg_ParseTuple/incorrect_converters/stderr.txt
+++ b/tests/cpychecker/PyArg_ParseTuple/incorrect_converters/stderr.txt
@@ -1,60 +1,60 @@
tests/cpychecker/PyArg_ParseTuple/incorrect_converters/input.c: In function 'incorrect_usages_of_converter':
-tests/cpychecker/PyArg_ParseTuple/incorrect_converters/input.c:36:26: error: Not enough arguments in call to PyArg_ParseTuple with format string "O&"
+tests/cpychecker/PyArg_ParseTuple/incorrect_converters/input.c:36:26: warning: Not enough arguments in call to PyArg_ParseTuple with format string "O&"
expected 2 extra arguments:
"int (converter)(PyObject *, T*)" for some type T
"T*" for some type T
but got none
- [-fpermissive]
-tests/cpychecker/PyArg_ParseTuple/incorrect_converters/input.c:39:26: error: Not enough arguments in call to PyArg_ParseTuple with format string "O&"
+ [enabled by default]
+tests/cpychecker/PyArg_ParseTuple/incorrect_converters/input.c:39:26: warning: Not enough arguments in call to PyArg_ParseTuple with format string "O&"
expected 2 extra arguments:
"int (converter)(PyObject *, T*)" for some type T
"T*" for some type T
but got 1:
"int"
- [-fpermissive]
-tests/cpychecker/PyArg_ParseTuple/incorrect_converters/input.c:44:26: error: Mismatching type in call to PyArg_ParseTuple with format code "O&" [-fpermissive]
+ [enabled by default]
+tests/cpychecker/PyArg_ParseTuple/incorrect_converters/input.c:44:26: warning: Mismatching type in call to PyArg_ParseTuple with format code "O&" [enabled by default]
argument 3 ("42") had type
"int"
but was expecting
"int (converter)(PyObject *, T*)" for some type T
for format code "O&"
-tests/cpychecker/PyArg_ParseTuple/incorrect_converters/input.c:49:26: error: Mismatching type in call to PyArg_ParseTuple with format code "O&" [-fpermissive]
+tests/cpychecker/PyArg_ParseTuple/incorrect_converters/input.c:49:26: warning: Mismatching type in call to PyArg_ParseTuple with format code "O&" [enabled by default]
argument 3 ("&i0") had type
"int *" (pointing to 32 bits)
but was expecting
"int (converter)(PyObject *, T*)" for some type T
for format code "O&"
-tests/cpychecker/PyArg_ParseTuple/incorrect_converters/input.c:54:26: error: Mismatching type in call to PyArg_ParseTuple with format code "O&" [-fpermissive]
+tests/cpychecker/PyArg_ParseTuple/incorrect_converters/input.c:54:26: warning: Mismatching type in call to PyArg_ParseTuple with format code "O&" [enabled by default]
argument 3 ("not_returning_int") had type
"void (*fn) ()"
but was expecting
"int (converter)(PyObject *, T*)" for some type T
for format code "O&"
-tests/cpychecker/PyArg_ParseTuple/incorrect_converters/input.c:57:26: error: Mismatching type in call to PyArg_ParseTuple with format code "O&" [-fpermissive]
+tests/cpychecker/PyArg_ParseTuple/incorrect_converters/input.c:57:26: warning: Mismatching type in call to PyArg_ParseTuple with format code "O&" [enabled by default]
argument 3 ("not_enough_args") had type
"int (*fn) (struct PyObject *)"
but was expecting
"int (converter)(PyObject *, T*)" for some type T
for format code "O&"
-tests/cpychecker/PyArg_ParseTuple/incorrect_converters/input.c:60:26: error: Mismatching type in call to PyArg_ParseTuple with format code "O&" [-fpermissive]
+tests/cpychecker/PyArg_ParseTuple/incorrect_converters/input.c:60:26: warning: Mismatching type in call to PyArg_ParseTuple with format code "O&" [enabled by default]
argument 3 ("too_many_args") had type
"int (*fn) (struct PyObject *, int *, int)"
but was expecting
"int (converter)(PyObject *, T*)" for some type T
for format code "O&"
-tests/cpychecker/PyArg_ParseTuple/incorrect_converters/input.c:63:26: error: Mismatching type in call to PyArg_ParseTuple with format code "O&" [-fpermissive]
+tests/cpychecker/PyArg_ParseTuple/incorrect_converters/input.c:63:26: warning: Mismatching type in call to PyArg_ParseTuple with format code "O&" [enabled by default]
argument 3 ("not_taking_PyObjectPtr") had type
"int (*fn) (int, int)"
but was expecting
"int (converter)(PyObject *, T*)" for some type T
for format code "O&"
-tests/cpychecker/PyArg_ParseTuple/incorrect_converters/input.c:68:26: error: Mismatching type in call to PyArg_ParseTuple with format code "O&" [-fpermissive]
+tests/cpychecker/PyArg_ParseTuple/incorrect_converters/input.c:68:26: warning: Mismatching type in call to PyArg_ParseTuple with format code "O&" [enabled by default]
argument 4 ("42") had type
"int"
but was expecting
"Py_ssize_t *" (pointing to 64 bits) (from second argument of "int (*fn) (struct PyObject *, Py_ssize_t *)")
for format code "O&"
-tests/cpychecker/PyArg_ParseTuple/incorrect_converters/input.c:73:26: error: Mismatching type in call to PyArg_ParseTuple with format code "O&" [-fpermissive]
+tests/cpychecker/PyArg_ParseTuple/incorrect_converters/input.c:73:26: warning: Mismatching type in call to PyArg_ParseTuple with format code "O&" [enabled by default]
argument 4 ("&i0") had type
"int *" (pointing to 32 bits)
but was expecting
diff --git a/tests/cpychecker/PyArg_ParseTuple/keywords/metadata.ini b/tests/cpychecker/PyArg_ParseTuple/keywords/metadata.ini
new file mode 100644
index 0000000..0d5711c
--- /dev/null
+++ b/tests/cpychecker/PyArg_ParseTuple/keywords/metadata.ini
@@ -0,0 +1,3 @@
+[ExpectedBehavior]
+# We expect only compilation *warnings*, so we expect a 0 exit code
+exitcode = 0
diff --git a/tests/cpychecker/PyArg_ParseTuple/keywords/stderr.txt b/tests/cpychecker/PyArg_ParseTuple/keywords/stderr.txt
index fe59eff..5a692dd 100644
--- a/tests/cpychecker/PyArg_ParseTuple/keywords/stderr.txt
+++ b/tests/cpychecker/PyArg_ParseTuple/keywords/stderr.txt
@@ -1,2 +1,2 @@
tests/cpychecker/PyArg_ParseTuple/keywords/input.c: In function 'parse_to_a_typedef':
-tests/cpychecker/PyArg_ParseTuple/keywords/input.c:32:37: error: keywords to PyArg_ParseTupleAndKeywords are not NULL-terminated [-fpermissive]
+tests/cpychecker/PyArg_ParseTuple/keywords/input.c:32:37: warning: keywords to PyArg_ParseTupleAndKeywords are not NULL-terminated [enabled by default]
diff --git a/tests/cpychecker/PyArg_ParseTuple/with_PY_SSIZE_T_CLEAN/metadata.ini b/tests/cpychecker/PyArg_ParseTuple/with_PY_SSIZE_T_CLEAN/metadata.ini
new file mode 100644
index 0000000..0d5711c
--- /dev/null
+++ b/tests/cpychecker/PyArg_ParseTuple/with_PY_SSIZE_T_CLEAN/metadata.ini
@@ -0,0 +1,3 @@
+[ExpectedBehavior]
+# We expect only compilation *warnings*, so we expect a 0 exit code
+exitcode = 0
diff --git a/tests/cpychecker/PyArg_ParseTuple/with_PY_SSIZE_T_CLEAN/stderr.txt b/tests/cpychecker/PyArg_ParseTuple/with_PY_SSIZE_T_CLEAN/stderr.txt
index b53cf69..e40944c 100644
--- a/tests/cpychecker/PyArg_ParseTuple/with_PY_SSIZE_T_CLEAN/stderr.txt
+++ b/tests/cpychecker/PyArg_ParseTuple/with_PY_SSIZE_T_CLEAN/stderr.txt
@@ -1,48 +1,48 @@
In file included from tests/cpychecker/PyArg_ParseTuple/with_PY_SSIZE_T_CLEAN/input.c:29:0:
tests/cpychecker/PyArg_ParseTuple/with_PY_SSIZE_T_CLEAN/../hash_format_codes.inc: In function 'hash_format_codes':
-tests/cpychecker/PyArg_ParseTuple/with_PY_SSIZE_T_CLEAN/../hash_format_codes.inc:49:26: error: Mismatching type in call to PyArg_ParseTuple with format code "s#" [-fpermissive]
+tests/cpychecker/PyArg_ParseTuple/with_PY_SSIZE_T_CLEAN/../hash_format_codes.inc:49:26: warning: Mismatching type in call to PyArg_ParseTuple with format code "s#" [enabled by default]
argument 4 ("&ival") had type
"int *" (pointing to 32 bits)
but was expecting
"Py_ssize_t *" (pointing to 64 bits)
for format code "s#"
-tests/cpychecker/PyArg_ParseTuple/with_PY_SSIZE_T_CLEAN/../hash_format_codes.inc:52:37: error: Mismatching type in call to PyArg_ParseTupleAndKeywords with format code "s#" [-fpermissive]
+tests/cpychecker/PyArg_ParseTuple/with_PY_SSIZE_T_CLEAN/../hash_format_codes.inc:52:37: warning: Mismatching type in call to PyArg_ParseTupleAndKeywords with format code "s#" [enabled by default]
argument 6 ("&ival") had type
"int *" (pointing to 32 bits)
but was expecting
"Py_ssize_t *" (pointing to 64 bits)
for format code "s#"
-tests/cpychecker/PyArg_ParseTuple/with_PY_SSIZE_T_CLEAN/../hash_format_codes.inc:72:26: error: Mismatching type in call to PyArg_ParseTuple with format code "z#" [-fpermissive]
+tests/cpychecker/PyArg_ParseTuple/with_PY_SSIZE_T_CLEAN/../hash_format_codes.inc:72:26: warning: Mismatching type in call to PyArg_ParseTuple with format code "z#" [enabled by default]
argument 4 ("&ival") had type
"int *" (pointing to 32 bits)
but was expecting
"Py_ssize_t *" (pointing to 64 bits)
for format code "z#"
-tests/cpychecker/PyArg_ParseTuple/with_PY_SSIZE_T_CLEAN/../hash_format_codes.inc:83:26: error: Mismatching type in call to PyArg_ParseTuple with format code "u#" [-fpermissive]
+tests/cpychecker/PyArg_ParseTuple/with_PY_SSIZE_T_CLEAN/../hash_format_codes.inc:83:26: warning: Mismatching type in call to PyArg_ParseTuple with format code "u#" [enabled by default]
argument 4 ("&ival") had type
"int *" (pointing to 32 bits)
but was expecting
"Py_ssize_t *" (pointing to 64 bits)
for format code "u#"
-tests/cpychecker/PyArg_ParseTuple/with_PY_SSIZE_T_CLEAN/../hash_format_codes.inc:94:26: error: Mismatching type in call to PyArg_ParseTuple with format code "es#" [-fpermissive]
+tests/cpychecker/PyArg_ParseTuple/with_PY_SSIZE_T_CLEAN/../hash_format_codes.inc:94:26: warning: Mismatching type in call to PyArg_ParseTuple with format code "es#" [enabled by default]
argument 5 ("&ival") had type
"int *" (pointing to 32 bits)
but was expecting
"Py_ssize_t *" (pointing to 64 bits)
for format code "es#"
-tests/cpychecker/PyArg_ParseTuple/with_PY_SSIZE_T_CLEAN/../hash_format_codes.inc:105:26: error: Mismatching type in call to PyArg_ParseTuple with format code "et#" [-fpermissive]
+tests/cpychecker/PyArg_ParseTuple/with_PY_SSIZE_T_CLEAN/../hash_format_codes.inc:105:26: warning: Mismatching type in call to PyArg_ParseTuple with format code "et#" [enabled by default]
argument 5 ("&ival") had type
"int *" (pointing to 32 bits)
but was expecting
"Py_ssize_t *" (pointing to 64 bits)
for format code "et#"
-tests/cpychecker/PyArg_ParseTuple/with_PY_SSIZE_T_CLEAN/../hash_format_codes.inc:116:26: error: Mismatching type in call to PyArg_ParseTuple with format code "t#" [-fpermissive]
+tests/cpychecker/PyArg_ParseTuple/with_PY_SSIZE_T_CLEAN/../hash_format_codes.inc:116:26: warning: Mismatching type in call to PyArg_ParseTuple with format code "t#" [enabled by default]
argument 4 ("&ival") had type
"int *" (pointing to 32 bits)
but was expecting
"Py_ssize_t *" (pointing to 64 bits)
for format code "t#"
-tests/cpychecker/PyArg_ParseTuple/with_PY_SSIZE_T_CLEAN/../hash_format_codes.inc:127:26: error: Mismatching type in call to PyArg_ParseTuple with format code "w#" [-fpermissive]
+tests/cpychecker/PyArg_ParseTuple/with_PY_SSIZE_T_CLEAN/../hash_format_codes.inc:127:26: warning: Mismatching type in call to PyArg_ParseTuple with format code "w#" [enabled by default]
argument 4 ("&ival") had type
"int *" (pointing to 32 bits)
but was expecting
diff --git a/tests/cpychecker/PyArg_ParseTuple/without_PY_SSIZE_T_CLEAN/metadata.ini b/tests/cpychecker/PyArg_ParseTuple/without_PY_SSIZE_T_CLEAN/metadata.ini
new file mode 100644
index 0000000..0d5711c
--- /dev/null
+++ b/tests/cpychecker/PyArg_ParseTuple/without_PY_SSIZE_T_CLEAN/metadata.ini
@@ -0,0 +1,3 @@
+[ExpectedBehavior]
+# We expect only compilation *warnings*, so we expect a 0 exit code
+exitcode = 0
diff --git a/tests/cpychecker/PyArg_ParseTuple/without_PY_SSIZE_T_CLEAN/stderr.txt b/tests/cpychecker/PyArg_ParseTuple/without_PY_SSIZE_T_CLEAN/stderr.txt
index b1c150e..1eb2fc8 100644
--- a/tests/cpychecker/PyArg_ParseTuple/without_PY_SSIZE_T_CLEAN/stderr.txt
+++ b/tests/cpychecker/PyArg_ParseTuple/without_PY_SSIZE_T_CLEAN/stderr.txt
@@ -1,48 +1,48 @@
In file included from tests/cpychecker/PyArg_ParseTuple/without_PY_SSIZE_T_CLEAN/input.c:28:0:
tests/cpychecker/PyArg_ParseTuple/without_PY_SSIZE_T_CLEAN/../hash_format_codes.inc: In function 'hash_format_codes':
-tests/cpychecker/PyArg_ParseTuple/without_PY_SSIZE_T_CLEAN/../hash_format_codes.inc:59:26: error: Mismatching type in call to PyArg_ParseTuple with format code "s#" [-fpermissive]
+tests/cpychecker/PyArg_ParseTuple/without_PY_SSIZE_T_CLEAN/../hash_format_codes.inc:59:26: warning: Mismatching type in call to PyArg_ParseTuple with format code "s#" [enabled by default]
argument 4 ("&sval") had type
"Py_ssize_t *" (pointing to 64 bits)
but was expecting
"int *" (pointing to 32 bits)
for format code "s#"
-tests/cpychecker/PyArg_ParseTuple/without_PY_SSIZE_T_CLEAN/../hash_format_codes.inc:62:37: error: Mismatching type in call to PyArg_ParseTupleAndKeywords with format code "s#" [-fpermissive]
+tests/cpychecker/PyArg_ParseTuple/without_PY_SSIZE_T_CLEAN/../hash_format_codes.inc:62:37: warning: Mismatching type in call to PyArg_ParseTupleAndKeywords with format code "s#" [enabled by default]
argument 6 ("&sval") had type
"Py_ssize_t *" (pointing to 64 bits)
but was expecting
"int *" (pointing to 32 bits)
for format code "s#"
-tests/cpychecker/PyArg_ParseTuple/without_PY_SSIZE_T_CLEAN/../hash_format_codes.inc:77:26: error: Mismatching type in call to PyArg_ParseTuple with format code "z#" [-fpermissive]
+tests/cpychecker/PyArg_ParseTuple/without_PY_SSIZE_T_CLEAN/../hash_format_codes.inc:77:26: warning: Mismatching type in call to PyArg_ParseTuple with format code "z#" [enabled by default]
argument 4 ("&sval") had type
"Py_ssize_t *" (pointing to 64 bits)
but was expecting
"int *" (pointing to 32 bits)
for format code "z#"
-tests/cpychecker/PyArg_ParseTuple/without_PY_SSIZE_T_CLEAN/../hash_format_codes.inc:88:26: error: Mismatching type in call to PyArg_ParseTuple with format code "u#" [-fpermissive]
+tests/cpychecker/PyArg_ParseTuple/without_PY_SSIZE_T_CLEAN/../hash_format_codes.inc:88:26: warning: Mismatching type in call to PyArg_ParseTuple with format code "u#" [enabled by default]
argument 4 ("&sval") had type
"Py_ssize_t *" (pointing to 64 bits)
but was expecting
"int *" (pointing to 32 bits)
for format code "u#"
-tests/cpychecker/PyArg_ParseTuple/without_PY_SSIZE_T_CLEAN/../hash_format_codes.inc:99:26: error: Mismatching type in call to PyArg_ParseTuple with format code "es#" [-fpermissive]
+tests/cpychecker/PyArg_ParseTuple/without_PY_SSIZE_T_CLEAN/../hash_format_codes.inc:99:26: warning: Mismatching type in call to PyArg_ParseTuple with format code "es#" [enabled by default]
argument 5 ("&sval") had type
"Py_ssize_t *" (pointing to 64 bits)
but was expecting
"int *" (pointing to 32 bits)
for format code "es#"
-tests/cpychecker/PyArg_ParseTuple/without_PY_SSIZE_T_CLEAN/../hash_format_codes.inc:110:26: error: Mismatching type in call to PyArg_ParseTuple with format code "et#" [-fpermissive]
+tests/cpychecker/PyArg_ParseTuple/without_PY_SSIZE_T_CLEAN/../hash_format_codes.inc:110:26: warning: Mismatching type in call to PyArg_ParseTuple with format code "et#" [enabled by default]
argument 5 ("&sval") had type
"Py_ssize_t *" (pointing to 64 bits)
but was expecting
"int *" (pointing to 32 bits)
for format code "et#"
-tests/cpychecker/PyArg_ParseTuple/without_PY_SSIZE_T_CLEAN/../hash_format_codes.inc:121:26: error: Mismatching type in call to PyArg_ParseTuple with format code "t#" [-fpermissive]
+tests/cpychecker/PyArg_ParseTuple/without_PY_SSIZE_T_CLEAN/../hash_format_codes.inc:121:26: warning: Mismatching type in call to PyArg_ParseTuple with format code "t#" [enabled by default]
argument 4 ("&sval") had type
"Py_ssize_t *" (pointing to 64 bits)
but was expecting
"int *" (pointing to 32 bits)
for format code "t#"
-tests/cpychecker/PyArg_ParseTuple/without_PY_SSIZE_T_CLEAN/../hash_format_codes.inc:132:26: error: Mismatching type in call to PyArg_ParseTuple with format code "w#" [-fpermissive]
+tests/cpychecker/PyArg_ParseTuple/without_PY_SSIZE_T_CLEAN/../hash_format_codes.inc:132:26: warning: Mismatching type in call to PyArg_ParseTuple with format code "w#" [enabled by default]
argument 4 ("&sval") had type
"Py_ssize_t *" (pointing to 64 bits)
but was expecting
12 years, 5 months
[gcc-python-plugin] add support for metadata.ini files to the test suite
by David Hugh Malcolm
commit 11acb9518e672f717ecb024118b5f0c1544bd3b9
Author: David Malcolm <dmalcolm(a)redhat.com>
Date: Tue Jan 3 17:32:33 2012 -0500
add support for metadata.ini files to the test suite
Add support to run-test-suite.py for reading an optional metadata.ini file
from the test's directory
Use this to implement overrides for the expected exit code for the two tests
that currently special-case it:
tests/cpychecker/refcounts/combinatorial-explosion
tests/examples/spelling-checker
run-test-suite.py | 58 +++++++++++---------
.../refcounts/combinatorial-explosion/metadata.ini | 4 ++
tests/examples/spelling-checker/metadata.ini | 4 ++
3 files changed, 41 insertions(+), 25 deletions(-)
---
diff --git a/run-test-suite.py b/run-test-suite.py
index 6ff3cca..9415e1d 100644
--- a/run-test-suite.py
+++ b/run-test-suite.py
@@ -1,5 +1,5 @@
-# Copyright 2011 David Malcolm <dmalcolm(a)redhat.com>
-# Copyright 2011 Red Hat, Inc.
+# Copyright 2011, 2012 David Malcolm <dmalcolm(a)redhat.com>
+# Copyright 2011, 2012 Red Hat, Inc.
#
# This is free software: you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by
@@ -25,11 +25,19 @@
# stderr.txt: (optional) as per stdout.txt
# getopts.py: (optional) if present, stdout from this script is
# added to GCC's invocation options
+# metadata.ini: (optional) if present, can override other properties of the
+# test (see below)
#
# This runner either invokes all tests, or just a subset, if supplied the
# names of the subdirectories as arguments. All test cases within the given
# directories will be run.
+# The optional metadata.ini can contain these sections:
+#
+# [ExpectedBehavior]
+# exitcode = integer value, for overriding defaults
+#
+
import glob
import os
import re
@@ -38,6 +46,7 @@ from distutils.sysconfig import get_python_inc
from subprocess import Popen, PIPE
import six
+from six.moves import configparser
from cpybuilder import CommandError
@@ -181,6 +190,9 @@ def run_test(testdir):
out = TestStream(os.path.join(testdir, 'stdout.txt'))
err = TestStream(os.path.join(testdir, 'stderr.txt'))
+ cp = configparser.SafeConfigParser()
+ cp.read([os.path.join(testdir, 'metadata.ini')])
+
env = dict(os.environ)
env['LC_ALL'] = 'C'
@@ -223,33 +235,29 @@ def run_test(testdir):
err.actual = err.actual.decode()
#print 'out: %r' % out.actual
#print 'err: %r' % err.actual
- c = p.wait()
-
- expsuccess = (err.expdata == '')
-
- # Special case:
- if testdir == 'tests/cpychecker/refcounts/combinatorial-explosion':
- # This test case should succeed, whilst emitting a note on stderr;
- # don't treat the stderr output as leading to an expected failure:
- expsuccess = True
-
- if testdir == 'tests/examples/spelling-checker':
- # This test case emits warnings on stderr;
- # don't treat the stderr output as leading to an expected failure:
- expsuccess = True
+ exitcode_actual = p.wait()
+
+ # Expected exit code
+ # By default, we expect success if the expected stderr is empty, and
+ # and failure if it's non-empty.
+ # This can be overridden if the test has a metadata.ini, by setting
+ # exitcode within the [ExpectedBehavior] section:
+ if err.expdata == '':
+ exitcode_expected = 0
+ else:
+ exitcode_expected = 1
+ if cp.has_section('ExpectedBehavior'):
+ if cp.has_option('ExpectedBehavior', 'exitcode'):
+ exitcode_expected = cp.getint('ExpectedBehavior', 'exitcode')
# Check exit code:
- if expsuccess:
- # Expect a successful exit:
- if c != 0:
- raise CompilationError(out.actual, err.actual, p, args)
+ if exitcode_actual != exitcode_expected:
+ sys.stderr.write(out.diff('stdout'))
+ sys.stderr.write(err.diff('stderr'))
+ raise CompilationError(out.actual, err.actual, p, args)
+
+ if exitcode_expected == 0:
assert os.path.exists(outfile)
- else:
- # Expect a failed exit:
- if c == 0:
- sys.stderr.write(out.diff('stdout'))
- sys.stderr.write(err.diff('stderr'))
- raise CompilationError(out.actual, err.actual, p, args)
out.check_for_diff(out.actual, err.actual, p, args, 'stdout', 0)
err.check_for_diff(out.actual, err.actual, p, args, 'stderr', 0)
diff --git a/tests/cpychecker/refcounts/combinatorial-explosion/metadata.ini b/tests/cpychecker/refcounts/combinatorial-explosion/metadata.ini
new file mode 100644
index 0000000..2fe6000
--- /dev/null
+++ b/tests/cpychecker/refcounts/combinatorial-explosion/metadata.ini
@@ -0,0 +1,4 @@
+[ExpectedBehavior]
+# This test case should succeed, whilst emitting a note on stderr;
+# don't treat the stderr output as leading to an expected failure:
+exitcode = 0
diff --git a/tests/examples/spelling-checker/metadata.ini b/tests/examples/spelling-checker/metadata.ini
new file mode 100644
index 0000000..ba7428c
--- /dev/null
+++ b/tests/examples/spelling-checker/metadata.ini
@@ -0,0 +1,4 @@
+[ExpectedBehavior]
+# This test case emits warnings on stderr;
+# don't treat the stderr output as leading to an expected failure:
+exitcode = 0
12 years, 5 months
[gcc-python-plugin] fix usage of gcc.warning in test code
by David Hugh Malcolm
commit 8e239def61dbe6e1281be707fd1eeae48beebd27
Author: David Malcolm <dmalcolm(a)redhat.com>
Date: Tue Jan 3 17:19:22 2012 -0500
fix usage of gcc.warning in test code
tests/examples/spelling-checker/script.py | 4 ++--
1 files changed, 2 insertions(+), 2 deletions(-)
---
diff --git a/tests/examples/spelling-checker/script.py b/tests/examples/spelling-checker/script.py
index fbc6347..f5e1785 100644
--- a/tests/examples/spelling-checker/script.py
+++ b/tests/examples/spelling-checker/script.py
@@ -39,8 +39,8 @@ class SpellcheckingPass(gcc.GimplePass):
# Warn about the spelling error (controlling the warning
# with the -Wall command-line option):
if gcc.warning(loc,
- gcc.Option('-Wall'),
- 'Possibly misspelt word in string constant: %r' % word):
+ '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)
12 years, 5 months
[gcc-python-plugin] move callback-handling code from gcc-python.c into a new gcc-python-callbacks.c file
by David Hugh Malcolm
commit 846f204b5e07f74c8beda21c5e678b82940391ac
Author: David Malcolm <dmalcolm(a)redhat.com>
Date: Tue Jan 3 15:40:54 2012 -0500
move callback-handling code from gcc-python.c into a new gcc-python-callbacks.c file
Makefile | 5 +-
gcc-python-callbacks.c | 317 ++++++++++++++++++++++++++++++++++++++++++++++++
gcc-python-wrappers.h | 10 ++-
gcc-python.c | 285 -------------------------------------------
4 files changed, 328 insertions(+), 289 deletions(-)
---
diff --git a/Makefile b/Makefile
index 6fd94d1..dce2b0d 100644
--- a/Makefile
+++ b/Makefile
@@ -1,5 +1,5 @@
-# Copyright 2011 David Malcolm <dmalcolm(a)redhat.com>
-# Copyright 2011 Red Hat, Inc.
+# Copyright 2011, 2012 David Malcolm <dmalcolm(a)redhat.com>
+# Copyright 2011, 2012 Red Hat, Inc.
#
# This is free software: you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by
@@ -20,6 +20,7 @@ GCC=gcc
PLUGIN_SOURCE_FILES= \
gcc-python.c \
gcc-python-attribute.c \
+ gcc-python-callbacks.c \
gcc-python-callgraph.c \
gcc-python-cfg.c \
gcc-python-closure.c \
diff --git a/gcc-python-callbacks.c b/gcc-python-callbacks.c
new file mode 100644
index 0000000..4100e55
--- /dev/null
+++ b/gcc-python-callbacks.c
@@ -0,0 +1,317 @@
+/*
+ Copyright 2011, 2012 David Malcolm <dmalcolm(a)redhat.com>
+ Copyright 2011, 2012 Red Hat, Inc.
+
+ This is free software: you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see
+ <http://www.gnu.org/licenses/>.
+*/
+
+#include <Python.h>
+#include "gcc-python.h"
+
+#include "gcc-python-closure.h"
+#include "gcc-python-wrappers.h"
+
+/*
+ Notes on the passes
+
+ As of 2011-03-30, http://gcc.gnu.org/onlinedocs/gccint/Plugins.html doesn't
+ seem to document the type of the gcc_data passed to each callback.
+
+ For reference, with gcc-4.6.0-0.15.fc15.x86_64 the types seem to be as
+ follows:
+
+ PLUGIN_ATTRIBUTES:
+ gcc_data=0x0
+ Called from: init_attributes () at ../../gcc/attribs.c:187
+ However, it seems at this point to have initialized these:
+ static const struct attribute_spec *attribute_tables[4];
+ static htab_t attribute_hash;
+
+ PLUGIN_PRAGMAS:
+ gcc_data=0x0
+ Called from: c_common_init () at ../../gcc/c-family/c-opts.c:1052
+
+ PLUGIN_START_UNIT:
+ gcc_data=0x0
+ Called from: compile_file () at ../../gcc/toplev.c:573
+
+ PLUGIN_PRE_GENERICIZE
+ gcc_data is: tree fndecl;
+ Called from: finish_function () at ../../gcc/c-decl.c:8323
+
+ PLUGIN_OVERRIDE_GATE
+ gcc_data:
+ &gate_status
+ bool gate_status;
+ Called from : execute_one_pass (pass=0x1011340) at ../../gcc/passes.c:1520
+
+ PLUGIN_PASS_EXECUTION
+ gcc_data: struct opt_pass *pass
+ Called from: execute_one_pass (pass=0x1011340) at ../../gcc/passes.c:1530
+
+ PLUGIN_ALL_IPA_PASSES_START
+ gcc_data=0x0
+ Called from: ipa_passes () at ../../gcc/cgraphunit.c:1779
+
+ PLUGIN_EARLY_GIMPLE_PASSES_START
+ gcc_data=0x0
+ Called from: execute_ipa_pass_list (pass=0x1011fa0) at ../../gcc/passes.c:1927
+
+ PLUGIN_EARLY_GIMPLE_PASSES_END
+ gcc_data=0x0
+ Called from: execute_ipa_pass_list (pass=0x1011fa0) at ../../gcc/passes.c:1930
+
+ PLUGIN_ALL_IPA_PASSES_END
+ gcc_data=0x0
+ Called from: ipa_passes () at ../../gcc/cgraphunit.c:1821
+
+ PLUGIN_ALL_PASSES_START
+ gcc_data=0x0
+ Called from: tree_rest_of_compilation (fndecl=0x7ffff16b1f00) at ../../gcc/tree-optimize.c:420
+
+ PLUGIN_ALL_PASSES_END
+ gcc_data=0x0
+ Called from: tree_rest_of_compilation (fndecl=0x7ffff16b1f00) at ../../gcc/tree-optimize.c:425
+
+ PLUGIN_FINISH_UNIT
+ gcc_data=0x0
+ Called from: compile_file () at ../../gcc/toplev.c:668
+
+ PLUGIN_FINISH
+ gcc_data=0x0
+ Called from: toplev_main (argc=17, argv=0x7fffffffdfc8) at ../../gcc/toplev.c:1970
+
+ PLUGIN_FINISH_TYPE
+ gcc_data=tree
+ Called from c_parser_declspecs (parser=0x7fffef559730, specs=0x15296d0, scspec_ok=1 '\001', typespec_ok=1 '\001', start_attr_ok=<optimized out>, la=cla_nonabstract_decl) at ../../gcc/c-parser.c:2111
+
+ PLUGIN_PRAGMA
+ gcc_data=0x0
+ Called from: init_pragma at ../../gcc/c-family/c-pragma.c:1321
+ to "Allow plugins to register their own pragmas."
+*/
+
+static enum plugin_event current_event = GCC_PYTHON_PLUGIN_BAD_EVENT;
+
+int gcc_python_is_within_event(enum plugin_event *out_event)
+{
+ if (current_event != GCC_PYTHON_PLUGIN_BAD_EVENT) {
+ if (out_event) {
+ *out_event = current_event;
+ }
+ return 1;
+ } else {
+ return 0;
+ }
+}
+
+
+static void
+gcc_python_finish_invoking_callback(PyGILState_STATE gstate,
+ int expect_wrapped_data, PyObject *wrapped_gcc_data,
+ void *user_data)
+ CPYCHECKER_STEALS_REFERENCE_TO_ARG(3) /* wrapped_gcc_data */ ;
+
+static void
+gcc_python_finish_invoking_callback(PyGILState_STATE gstate,
+ int expect_wrapped_data, PyObject *wrapped_gcc_data,
+ void *user_data)
+{
+ struct callback_closure *closure = (struct callback_closure *)user_data;
+ PyObject *args = NULL;
+ PyObject *result = NULL;
+ location_t saved_loc = input_location;
+ enum plugin_event saved_event;
+
+ assert(closure);
+ /* We take ownership of wrapped_gcc_data.
+ For some callbacks types it will always be NULL; for others, it's only
+ NULL if an error has occurred: */
+ if (expect_wrapped_data && !wrapped_gcc_data) {
+ goto cleanup;
+ }
+
+ if (cfun) {
+ /* Temporarily override input_location to the top of the function: */
+ input_location = cfun->function_start_locus;
+ }
+
+ args = gcc_python_closure_make_args(closure, 1, wrapped_gcc_data);
+ if (!args) {
+ goto cleanup;
+ }
+
+ saved_event = current_event;
+ current_event = closure->event;
+
+ result = PyObject_Call(closure->callback, args, closure->kwargs);
+
+ current_event = saved_event;
+
+ if (!result) {
+ /* Treat an unhandled Python error as a compilation error: */
+ gcc_python_print_exception("Unhandled Python exception raised within callback");
+ }
+
+ // FIXME: the result is ignored
+
+cleanup:
+ Py_XDECREF(wrapped_gcc_data);
+ Py_XDECREF(args);
+ Py_XDECREF(result);
+
+ PyGILState_Release(gstate);
+ input_location = saved_loc;
+}
+
+/*
+ C-level callbacks for each event ID follow, thunking into the registered
+ Python callable.
+
+ There's some repetition here, but it can be easier to debug if you have
+ separate breakpoint locations for each event ID.
+ */
+
+static void
+gcc_python_callback_for_tree(void *gcc_data, void *user_data)
+{
+ PyGILState_STATE gstate;
+ tree t = (tree)gcc_data;
+
+ gstate = PyGILState_Ensure();
+
+ gcc_python_finish_invoking_callback(gstate,
+ 1, gcc_python_make_wrapper_tree(t),
+ user_data);
+}
+
+
+static void
+gcc_python_callback_for_PLUGIN_ATTRIBUTES(void *gcc_data, void *user_data)
+{
+ PyGILState_STATE gstate;
+
+ //printf("%s:%i:(%p, %p)\n", __FILE__, __LINE__, gcc_data, user_data);
+
+ gstate = PyGILState_Ensure();
+
+ gcc_python_finish_invoking_callback(gstate,
+ 0, NULL,
+ user_data);
+}
+
+static void
+gcc_python_callback_for_PLUGIN_PASS_EXECUTION(void *gcc_data, void *user_data)
+{
+ PyGILState_STATE gstate;
+ struct opt_pass *pass = (struct opt_pass *)gcc_data;
+
+ //printf("%s:%i:(%p, %p)\n", __FILE__, __LINE__, gcc_data, user_data);
+ assert(pass);
+
+ gstate = PyGILState_Ensure();
+
+ gcc_python_finish_invoking_callback(gstate,
+ 1, gcc_python_make_wrapper_pass(pass),
+ user_data);
+}
+
+
+
+static void
+gcc_python_callback_for_FINISH_UNIT(void *gcc_data, void *user_data)
+{
+ PyGILState_STATE gstate;
+
+ gstate = PyGILState_Ensure();
+
+ gcc_python_finish_invoking_callback(gstate,
+ 0, NULL,
+ user_data);
+}
+
+
+
+PyObject*
+gcc_python_register_callback(PyObject *self, PyObject *args, PyObject *kwargs)
+{
+ int event;
+ PyObject *callback = NULL;
+ PyObject *extraargs = NULL;
+ struct callback_closure *closure;
+
+ if (!PyArg_ParseTuple(args, "iO|O:register_callback", &event, &callback, &extraargs)) {
+ return NULL;
+ }
+
+ //printf("%s:%i:gcc_python_register_callback\n", __FILE__, __LINE__);
+
+ closure = gcc_python_closure_new_for_plugin_event(callback, extraargs, kwargs,
+ (enum plugin_event)event);
+ if (!closure) {
+ return PyErr_NoMemory();
+ }
+
+ switch ((enum plugin_event)event) {
+ case PLUGIN_ATTRIBUTES:
+ register_callback("python", // FIXME
+ (enum plugin_event)event,
+ gcc_python_callback_for_PLUGIN_ATTRIBUTES,
+ closure);
+ break;
+
+ case PLUGIN_PRE_GENERICIZE:
+ register_callback("python", // FIXME
+ (enum plugin_event)event,
+ gcc_python_callback_for_tree,
+ closure);
+ break;
+
+ case PLUGIN_PASS_EXECUTION:
+ register_callback("python", // FIXME
+ (enum plugin_event)event,
+ gcc_python_callback_for_PLUGIN_PASS_EXECUTION,
+ closure);
+ break;
+
+ case PLUGIN_FINISH_UNIT:
+ register_callback("python", // FIXME
+ (enum plugin_event)event,
+ gcc_python_callback_for_FINISH_UNIT,
+ closure);
+ break;
+
+ case PLUGIN_FINISH_TYPE:
+ register_callback("python", // FIXME
+ (enum plugin_event)event,
+ gcc_python_callback_for_tree,
+ closure);
+ break;
+
+ default:
+ PyErr_Format(PyExc_ValueError, "event type %i invalid (or not wired up yet)", event);
+ return NULL;
+ }
+
+ Py_RETURN_NONE;
+}
+
+/*
+ PEP-7
+Local variables:
+c-basic-offset: 4
+indent-tabs-mode: nil
+End:
+*/
diff --git a/gcc-python-wrappers.h b/gcc-python-wrappers.h
index 9557a7b..d260315 100644
--- a/gcc-python-wrappers.h
+++ b/gcc-python-wrappers.h
@@ -1,6 +1,6 @@
/*
- Copyright 2011 David Malcolm <dmalcolm(a)redhat.com>
- Copyright 2011 Red Hat, Inc.
+ Copyright 2011, 2012 David Malcolm <dmalcolm(a)redhat.com>
+ Copyright 2011, 2012 Red Hat, Inc.
This is free software: you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
@@ -31,6 +31,12 @@ PyMODINIT_FUNC initoptpass(void);
PyObject*
gcc_python_register_attribute(PyObject *self, PyObject *args, PyObject *kwargs);
+/* gcc-python-callbacks.c: */
+int gcc_python_is_within_event(enum plugin_event *out_event);
+
+PyObject*
+gcc_python_register_callback(PyObject *self, PyObject *args, PyObject *kwargs);
+
/* gcc-python-callgraph.c: */
PyObject *
gcc_CallgraphEdge_repr(struct PyGccCallgraphEdge * self);
diff --git a/gcc-python.c b/gcc-python.c
index 8f94d2f..4b962d9 100644
--- a/gcc-python.c
+++ b/gcc-python.c
@@ -53,86 +53,6 @@ static const char* event_name[] = {
# undef DEFEVENT
};
-/*
- Notes on the passes
-
- As of 2011-03-30, http://gcc.gnu.org/onlinedocs/gccint/Plugins.html doesn't
- seem to document the type of the gcc_data passed to each callback.
-
- For reference, with gcc-4.6.0-0.15.fc15.x86_64 the types seem to be as
- follows:
-
- PLUGIN_ATTRIBUTES:
- gcc_data=0x0
- Called from: init_attributes () at ../../gcc/attribs.c:187
- However, it seems at this point to have initialized these:
- static const struct attribute_spec *attribute_tables[4];
- static htab_t attribute_hash;
-
- PLUGIN_PRAGMAS:
- gcc_data=0x0
- Called from: c_common_init () at ../../gcc/c-family/c-opts.c:1052
-
- PLUGIN_START_UNIT:
- gcc_data=0x0
- Called from: compile_file () at ../../gcc/toplev.c:573
-
- PLUGIN_PRE_GENERICIZE
- gcc_data is: tree fndecl;
- Called from: finish_function () at ../../gcc/c-decl.c:8323
-
- PLUGIN_OVERRIDE_GATE
- gcc_data:
- &gate_status
- bool gate_status;
- Called from : execute_one_pass (pass=0x1011340) at ../../gcc/passes.c:1520
-
- PLUGIN_PASS_EXECUTION
- gcc_data: struct opt_pass *pass
- Called from: execute_one_pass (pass=0x1011340) at ../../gcc/passes.c:1530
-
- PLUGIN_ALL_IPA_PASSES_START
- gcc_data=0x0
- Called from: ipa_passes () at ../../gcc/cgraphunit.c:1779
-
- PLUGIN_EARLY_GIMPLE_PASSES_START
- gcc_data=0x0
- Called from: execute_ipa_pass_list (pass=0x1011fa0) at ../../gcc/passes.c:1927
-
- PLUGIN_EARLY_GIMPLE_PASSES_END
- gcc_data=0x0
- Called from: execute_ipa_pass_list (pass=0x1011fa0) at ../../gcc/passes.c:1930
-
- PLUGIN_ALL_IPA_PASSES_END
- gcc_data=0x0
- Called from: ipa_passes () at ../../gcc/cgraphunit.c:1821
-
- PLUGIN_ALL_PASSES_START
- gcc_data=0x0
- Called from: tree_rest_of_compilation (fndecl=0x7ffff16b1f00) at ../../gcc/tree-optimize.c:420
-
- PLUGIN_ALL_PASSES_END
- gcc_data=0x0
- Called from: tree_rest_of_compilation (fndecl=0x7ffff16b1f00) at ../../gcc/tree-optimize.c:425
-
- PLUGIN_FINISH_UNIT
- gcc_data=0x0
- Called from: compile_file () at ../../gcc/toplev.c:668
-
- PLUGIN_FINISH
- gcc_data=0x0
- Called from: toplev_main (argc=17, argv=0x7fffffffdfc8) at ../../gcc/toplev.c:1970
-
- PLUGIN_FINISH_TYPE
- gcc_data=tree
- Called from c_parser_declspecs (parser=0x7fffef559730, specs=0x15296d0, scspec_ok=1 '\001', typespec_ok=1 '\001', start_attr_ok=<optimized out>, la=cla_nonabstract_decl) at ../../gcc/c-parser.c:2111
-
- PLUGIN_PRAGMA
- gcc_data=0x0
- Called from: init_pragma at ../../gcc/c-family/c-pragma.c:1321
- to "Allow plugins to register their own pragmas."
-*/
-
static void
trace_callback(enum plugin_event event, void *gcc_data, void *user_data)
{
@@ -151,211 +71,6 @@ static void trace_callback_for_##NAME(void *gcc_data, void *user_data) \
# undef DEFEVENT
#endif /* GCC_PYTHON_TRACE_ALL_EVENTS */
-static enum plugin_event current_event = GCC_PYTHON_PLUGIN_BAD_EVENT;
-
-int gcc_python_is_within_event(enum plugin_event *out_event)
-{
- if (current_event != GCC_PYTHON_PLUGIN_BAD_EVENT) {
- if (out_event) {
- *out_event = current_event;
- }
- return 1;
- } else {
- return 0;
- }
-}
-
-
-static void
-gcc_python_finish_invoking_callback(PyGILState_STATE gstate,
- int expect_wrapped_data, PyObject *wrapped_gcc_data,
- void *user_data)
- CPYCHECKER_STEALS_REFERENCE_TO_ARG(3) /* wrapped_gcc_data */ ;
-
-static void
-gcc_python_finish_invoking_callback(PyGILState_STATE gstate,
- int expect_wrapped_data, PyObject *wrapped_gcc_data,
- void *user_data)
-{
- struct callback_closure *closure = (struct callback_closure *)user_data;
- PyObject *args = NULL;
- PyObject *result = NULL;
- location_t saved_loc = input_location;
- enum plugin_event saved_event;
-
- assert(closure);
- /* We take ownership of wrapped_gcc_data.
- For some callbacks types it will always be NULL; for others, it's only
- NULL if an error has occurred: */
- if (expect_wrapped_data && !wrapped_gcc_data) {
- goto cleanup;
- }
-
- if (cfun) {
- /* Temporarily override input_location to the top of the function: */
- input_location = cfun->function_start_locus;
- }
-
- args = gcc_python_closure_make_args(closure, 1, wrapped_gcc_data);
- if (!args) {
- goto cleanup;
- }
-
- saved_event = current_event;
- current_event = closure->event;
-
- result = PyObject_Call(closure->callback, args, closure->kwargs);
-
- current_event = saved_event;
-
- if (!result) {
- /* Treat an unhandled Python error as a compilation error: */
- gcc_python_print_exception("Unhandled Python exception raised within callback");
- }
-
- // FIXME: the result is ignored
-
-cleanup:
- Py_XDECREF(wrapped_gcc_data);
- Py_XDECREF(args);
- Py_XDECREF(result);
-
- PyGILState_Release(gstate);
- input_location = saved_loc;
-}
-
-/*
- C-level callbacks for each event ID follow, thunking into the registered
- Python callable.
-
- There's some repetition here, but it can be easier to debug if you have
- separate breakpoint locations for each event ID.
- */
-
-static void
-gcc_python_callback_for_tree(void *gcc_data, void *user_data)
-{
- PyGILState_STATE gstate;
- tree t = (tree)gcc_data;
-
- gstate = PyGILState_Ensure();
-
- gcc_python_finish_invoking_callback(gstate,
- 1, gcc_python_make_wrapper_tree(t),
- user_data);
-}
-
-
-static void
-gcc_python_callback_for_PLUGIN_ATTRIBUTES(void *gcc_data, void *user_data)
-{
- PyGILState_STATE gstate;
-
- //printf("%s:%i:(%p, %p)\n", __FILE__, __LINE__, gcc_data, user_data);
-
- gstate = PyGILState_Ensure();
-
- gcc_python_finish_invoking_callback(gstate,
- 0, NULL,
- user_data);
-}
-
-static void
-gcc_python_callback_for_PLUGIN_PASS_EXECUTION(void *gcc_data, void *user_data)
-{
- PyGILState_STATE gstate;
- struct opt_pass *pass = (struct opt_pass *)gcc_data;
-
- //printf("%s:%i:(%p, %p)\n", __FILE__, __LINE__, gcc_data, user_data);
- assert(pass);
-
- gstate = PyGILState_Ensure();
-
- gcc_python_finish_invoking_callback(gstate,
- 1, gcc_python_make_wrapper_pass(pass),
- user_data);
-}
-
-
-
-static void
-gcc_python_callback_for_FINISH_UNIT(void *gcc_data, void *user_data)
-{
- PyGILState_STATE gstate;
-
- gstate = PyGILState_Ensure();
-
- gcc_python_finish_invoking_callback(gstate,
- 0, NULL,
- user_data);
-}
-
-
-
-static PyObject*
-gcc_python_register_callback(PyObject *self, PyObject *args, PyObject *kwargs)
-{
- int event;
- PyObject *callback = NULL;
- PyObject *extraargs = NULL;
- struct callback_closure *closure;
-
- if (!PyArg_ParseTuple(args, "iO|O:register_callback", &event, &callback, &extraargs)) {
- return NULL;
- }
-
- //printf("%s:%i:gcc_python_register_callback\n", __FILE__, __LINE__);
-
- closure = gcc_python_closure_new_for_plugin_event(callback, extraargs, kwargs,
- (enum plugin_event)event);
- if (!closure) {
- return PyErr_NoMemory();
- }
-
- switch ((enum plugin_event)event) {
- case PLUGIN_ATTRIBUTES:
- register_callback("python", // FIXME
- (enum plugin_event)event,
- gcc_python_callback_for_PLUGIN_ATTRIBUTES,
- closure);
- break;
-
- case PLUGIN_PRE_GENERICIZE:
- register_callback("python", // FIXME
- (enum plugin_event)event,
- gcc_python_callback_for_tree,
- closure);
- break;
-
- case PLUGIN_PASS_EXECUTION:
- register_callback("python", // FIXME
- (enum plugin_event)event,
- gcc_python_callback_for_PLUGIN_PASS_EXECUTION,
- closure);
- break;
-
- case PLUGIN_FINISH_UNIT:
- register_callback("python", // FIXME
- (enum plugin_event)event,
- gcc_python_callback_for_FINISH_UNIT,
- closure);
- break;
-
- case PLUGIN_FINISH_TYPE:
- register_callback("python", // FIXME
- (enum plugin_event)event,
- gcc_python_callback_for_tree,
- closure);
- break;
-
- default:
- PyErr_Format(PyExc_ValueError, "event type %i invalid (or not wired up yet)", event);
- return NULL;
- }
-
- Py_RETURN_NONE;
-}
-
static PyObject*
gcc_python_define_macro(PyObject *self,
PyObject *args, PyObject *kwargs)
12 years, 5 months
[gcc-python-plugin] move diagnostics code from gcc-python.c into a new gcc-python-diagnostics.c
by David Hugh Malcolm
commit 5ec25a6631c8bf72ed155b9ac9f9461240a28123
Author: David Malcolm <dmalcolm(a)redhat.com>
Date: Tue Jan 3 15:28:17 2012 -0500
move diagnostics code from gcc-python.c into a new gcc-python-diagnostics.c
Makefile | 1 +
gcc-python-diagnostics.c | 170 ++++++++++++++++++++++++++++++++++++++++++++++
gcc-python-wrappers.h | 13 ++++
gcc-python.c | 137 -------------------------------------
4 files changed, 184 insertions(+), 137 deletions(-)
---
diff --git a/Makefile b/Makefile
index 8c62ef9..6fd94d1 100644
--- a/Makefile
+++ b/Makefile
@@ -23,6 +23,7 @@ PLUGIN_SOURCE_FILES= \
gcc-python-callgraph.c \
gcc-python-cfg.c \
gcc-python-closure.c \
+ gcc-python-diagnostics.c \
gcc-python-function.c \
gcc-python-gimple.c \
gcc-python-location.c \
diff --git a/gcc-python-diagnostics.c b/gcc-python-diagnostics.c
new file mode 100644
index 0000000..b3e509c
--- /dev/null
+++ b/gcc-python-diagnostics.c
@@ -0,0 +1,170 @@
+/*
+ Copyright 2011, 2012 David Malcolm <dmalcolm(a)redhat.com>
+ Copyright 2011, 2012 Red Hat, Inc.
+
+ This is free software: you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see
+ <http://www.gnu.org/licenses/>.
+*/
+
+#include <Python.h>
+#include "gcc-python.h"
+
+#include "gcc-python-wrappers.h"
+
+#include "diagnostic.h"
+
+/*
+ I initially attempted to directly wrap gcc's:
+ diagnostic_report_diagnostic()
+ given that that seems to be the abstraction within gcc/diagnostic.h: all
+ instances of (struct diagnostic_info) within the gcc source tree seem to
+ be allocated on the stack, within functions exposed in gcc/diagnostic.h
+
+ However, diagnostic_report_diagnostic() ultimately calls into the
+ pretty-printing routines, trying to format varargs, which doesn't make much
+ sense for us: we have first-class string objects and string formatting at
+ the python level.
+
+ Thus we instead just wrap "error_at" and its analogs
+*/
+
+PyObject*
+gcc_python_permerror(PyObject *self, PyObject *args)
+{
+ PyGccLocation *loc_obj = NULL;
+ const char *msgid = NULL;
+ PyObject *result_obj = NULL;
+ bool result_b;
+
+ if (!PyArg_ParseTuple(args,
+ "O!"
+ "s"
+ ":permerror",
+ &gcc_LocationType, &loc_obj,
+ &msgid)) {
+ return NULL;
+ }
+
+ /* Invoke the GCC function: */
+ result_b = permerror(loc_obj->loc, "%s", msgid);
+
+ result_obj = PyBool_FromLong(result_b);
+
+ return result_obj;
+}
+
+PyObject *
+gcc_python_error(PyObject *self, PyObject *args, PyObject *kwargs)
+{
+ PyGccLocation *loc_obj;
+ const char *msg;
+ char *keywords[] = {"location",
+ "message",
+ NULL};
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwargs,
+ "O!s:error", keywords,
+ &gcc_LocationType, &loc_obj,
+ &msg)) {
+ return NULL;
+ }
+
+ error_at(loc_obj->loc, "%s", msg);
+
+ Py_RETURN_NONE;
+}
+
+PyObject *
+gcc_python_warning(PyObject *self, PyObject *args, PyObject *kwargs)
+{
+ PyGccLocation *loc_obj;
+ const char *msg;
+ PyObject *opt_obj = &_Py_NoneStruct;
+ int opt_code;
+ char *keywords[] = {"location",
+ "message",
+ "option",
+ NULL};
+ bool was_reported;
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwargs,
+ "O!s|O:warning", keywords,
+
+ /* code "O!": */
+ &gcc_LocationType, &loc_obj,
+ /* code: "s": */
+ &msg,
+
+ /* optional args: */
+ /* code: "O": */
+ &opt_obj)) {
+ return NULL;
+ }
+
+ assert(opt_obj);
+
+ /* If a gcc.Option was given, extract the code: */
+ if (Py_TYPE(opt_obj) == &gcc_OptionType) {
+ opt_code = ((PyGccOption*)opt_obj)->opt_code;
+
+ /* Ugly workaround; see this function: */
+ if (0 == gcc_python_option_is_enabled(opt_code)) {
+ return PyBool_FromLong(0);
+ }
+
+ } else {
+ if (opt_obj == &_Py_NoneStruct) {
+ /* No gcc.Option given: an unconditionally enabled warning: */
+ opt_code = 0;
+ } else {
+ /* Some other object was given: */
+ return PyErr_Format(PyExc_TypeError,
+ ("option must be either None,"
+ " or of type gcc.Option"));
+ }
+ }
+
+ was_reported = warning_at(loc_obj->loc, opt_code, "%s", msg);
+
+ return PyBool_FromLong(was_reported);
+}
+
+PyObject *
+gcc_python_inform(PyObject *self, PyObject *args, PyObject *kwargs)
+{
+ PyGccLocation *loc_obj;
+ const char *msg;
+ char *keywords[] = {"location",
+ "message",
+ NULL};
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwargs,
+ "O!s:inform", keywords,
+ &gcc_LocationType, &loc_obj,
+ &msg)) {
+ return NULL;
+ }
+
+ inform(loc_obj->loc, "%s", msg);
+
+ Py_RETURN_NONE;
+}
+
+/*
+ PEP-7
+Local variables:
+c-basic-offset: 4
+indent-tabs-mode: nil
+End:
+*/
diff --git a/gcc-python-wrappers.h b/gcc-python-wrappers.h
index b1f3986..9557a7b 100644
--- a/gcc-python-wrappers.h
+++ b/gcc-python-wrappers.h
@@ -50,6 +50,19 @@ gcc_CallgraphNode_get_callers(struct PyGccCallgraphNode * self);
extern PyObject *
gcc_CallgraphNode_get_callees(struct PyGccCallgraphNode * self);
+/* gcc-python-diagnostics.c: */
+PyObject*
+gcc_python_permerror(PyObject *self, PyObject *args);
+
+PyObject *
+gcc_python_error(PyObject *self, PyObject *args, PyObject *kwargs);
+
+PyObject *
+gcc_python_warning(PyObject *self, PyObject *args, PyObject *kwargs);
+
+PyObject *
+gcc_python_inform(PyObject *self, PyObject *args, PyObject *kwargs);
+
/* gcc-python-pass.c: */
extern PyObject *
gcc_python_make_wrapper_pass(struct opt_pass *pass);
diff --git a/gcc-python.c b/gcc-python.c
index 0ae9f21..8f94d2f 100644
--- a/gcc-python.c
+++ b/gcc-python.c
@@ -391,143 +391,6 @@ gcc_python_define_macro(PyObject *self,
Py_RETURN_NONE;
}
-/*
- I initially attempted to directly wrap gcc's:
- diagnostic_report_diagnostic()
- given that that seems to be the abstraction within gcc/diagnostic.h: all
- instances of (struct diagnostic_info) within the gcc source tree seem to
- be allocated on the stack, within functions exposed in gcc/diagnostic.h
-
- However, diagnostic_report_diagnostic() ultimately calls into the
- pretty-printing routines, trying to format varargs, which doesn't make much
- sense for us: we have first-class string objects and string formatting at
- the python level.
-
- Thus we instead just wrap "error_at" and its analogs
-*/
-
-static PyObject*
-gcc_python_permerror(PyObject *self, PyObject *args)
-{
- PyGccLocation *loc_obj = NULL;
- const char *msgid = NULL;
- PyObject *result_obj = NULL;
- bool result_b;
-
- if (!PyArg_ParseTuple(args,
- "O!"
- "s"
- ":permerror",
- &gcc_LocationType, &loc_obj,
- &msgid)) {
- return NULL;
- }
-
- /* Invoke the GCC function: */
- result_b = permerror(loc_obj->loc, "%s", msgid);
-
- result_obj = PyBool_FromLong(result_b);
-
- return result_obj;
-}
-
-static PyObject *
-gcc_python_error(PyObject *self, PyObject *args, PyObject *kwargs)
-{
- PyGccLocation *loc_obj;
- const char *msg;
- char *keywords[] = {"location",
- "message",
- NULL};
-
- if (!PyArg_ParseTupleAndKeywords(args, kwargs,
- "O!s:error", keywords,
- &gcc_LocationType, &loc_obj,
- &msg)) {
- return NULL;
- }
-
- error_at(loc_obj->loc, "%s", msg);
-
- Py_RETURN_NONE;
-}
-
-static PyObject *
-gcc_python_warning(PyObject *self, PyObject *args, PyObject *kwargs)
-{
- PyGccLocation *loc_obj;
- const char *msg;
- PyObject *opt_obj = &_Py_NoneStruct;
- int opt_code;
- char *keywords[] = {"location",
- "message",
- "option",
- NULL};
- bool was_reported;
-
- if (!PyArg_ParseTupleAndKeywords(args, kwargs,
- "O!s|O:warning", keywords,
-
- /* code "O!": */
- &gcc_LocationType, &loc_obj,
- /* code: "s": */
- &msg,
-
- /* optional args: */
- /* code: "O": */
- &opt_obj)) {
- return NULL;
- }
-
- assert(opt_obj);
-
- /* If a gcc.Option was given, extract the code: */
- if (Py_TYPE(opt_obj) == &gcc_OptionType) {
- opt_code = ((PyGccOption*)opt_obj)->opt_code;
-
- /* Ugly workaround; see this function: */
- if (0 == gcc_python_option_is_enabled(opt_code)) {
- return PyBool_FromLong(0);
- }
-
- } else {
- if (opt_obj == &_Py_NoneStruct) {
- /* No gcc.Option given: an unconditionally enabled warning: */
- opt_code = 0;
- } else {
- /* Some other object was given: */
- return PyErr_Format(PyExc_TypeError,
- ("option must be either None,"
- " or of type gcc.Option"));
- }
- }
-
- was_reported = warning_at(loc_obj->loc, opt_code, "%s", msg);
-
- return PyBool_FromLong(was_reported);
-}
-
-static PyObject *
-gcc_python_inform(PyObject *self, PyObject *args, PyObject *kwargs)
-{
- PyGccLocation *loc_obj;
- const char *msg;
- char *keywords[] = {"location",
- "message",
- NULL};
-
- if (!PyArg_ParseTupleAndKeywords(args, kwargs,
- "O!s:inform", keywords,
- &gcc_LocationType, &loc_obj,
- &msg)) {
- return NULL;
- }
-
- inform(loc_obj->loc, "%s", msg);
-
- Py_RETURN_NONE;
-}
-
static PyObject *
gcc_python_set_location(PyObject *self, PyObject *args)
{
12 years, 5 months
[gcc-python-plugin] support emitting unconditional warnings
by David Hugh Malcolm
commit 2801c82a909473ab9ce27f4975c870d524795ed5
Author: David Malcolm <dmalcolm(a)redhat.com>
Date: Tue Jan 3 14:11:27 2012 -0500
support emitting unconditional warnings
Make the "option" argument to gcc.warning be optional: if not provided, an
unconditional warning is emitted.
I believe this argument will be rarely used (until we can add new command-line
options), so it makes sense to make it optional, moving it to the end of the
positional arguments.
This reorders the arguments to gcc.warning, but there are no uses of this
entrypoint within the source tree (other than test code), and a review of all
code posted by others to the mailing list showed no usage of the entrypoint
either.
Fixes ticket #8:
https://fedorahosted.org/gcc-python-plugin/ticket/8 */
Also, fix the order of the command-line arguments to gcc-with-python in the
usage examples: some erroneously contained gcc options before the python
script name (which must come first).
docs/basics.rst | 34 ++++++++++++++++++++-----
gcc-python.c | 47 ++++++++++++++++++++++++++--------
tests/plugin/diagnostics/script.py | 25 ++++++++++++++++--
tests/plugin/diagnostics/stderr.txt | 3 ++
4 files changed, 88 insertions(+), 21 deletions(-)
---
diff --git a/docs/basics.rst b/docs/basics.rst
index 7987a4f..1ca3116 100644
--- a/docs/basics.rst
+++ b/docs/basics.rst
@@ -481,15 +481,35 @@ Currently useful callback events
Generating custom errors and warnings
=====================================
-.. py:function:: gcc.warning(location, option, message)
+.. py:function:: gcc.warning(location, message, option=None)
- Emits a compiler warning at the given :py:class:`gcc.Location`.
+ Emits a compiler warning at the given :py:class:`gcc.Location`, potentially
+ controlled by a :py:class:`gcc.Option`.
- The warning is controlled by the given :py:class:`gcc.Option`.
+ If no option is supplied (or `None` is supplied), then the warning is an
+ unconditional one, always issued::
+
+ gcc.warning(func.start, 'this is an unconditional warning')
+
+ .. code-block:: bash
+
+ $ ./gcc-with-python script.py input.c
+ input.c:25:1: warning: this is an unconditional warning [enabled by default]
+
+ and will be an error if `-Werror` is supplied as a command-line argument to
+ GCC:
+
+ .. code-block:: bash
+
+ $ ./gcc-with-python script.py -Werror input.c
+ input.c:25:1: error: this is an unconditional warning [-Werror]
+
+ It's possible to associate the warning with a command-line option, so that
+ it is controlled by that option.
For example, given this Python code::
- gcc.warning(func.start, gcc.Option('-Wformat'), 'Incorrect formatting')
+ gcc.warning(func.start, 'Incorrect formatting', gcc.Option('-Wformat'))
if the given warning is enabled, a warning will be printed to stderr:
@@ -503,13 +523,13 @@ Generating custom errors and warnings
.. code-block:: bash
- $ ./gcc-with-python -Werror script.py input.c
+ $ ./gcc-with-python script.py -Werror input.c
input.c:25:1: error: incorrect formatting [-Werror=format]
cc1: all warnings being treated as errors
.. code-block:: bash
- $ ./gcc-with-python -Werror=format script.py input.c
+ $ ./gcc-with-python script.py -Werror=format input.c
input.c:25:1: error: incorrect formatting [-Werror=format]
cc1: some warnings being treated as errors
@@ -517,7 +537,7 @@ Generating custom errors and warnings
.. code-block:: bash
- $ ./gcc-with-python -Wno-format script.py input.c
+ $ ./gcc-with-python script.py -Wno-format input.c
.. note:: Due to the way GCC implements some options, it's not always
possible for the plugin to fully disable some warnings. See
diff --git a/gcc-python.c b/gcc-python.c
index 8417d70..0ae9f21 100644
--- a/gcc-python.c
+++ b/gcc-python.c
@@ -1,6 +1,6 @@
/*
- Copyright 2011 David Malcolm <dmalcolm(a)redhat.com>
- Copyright 2011 Red Hat, Inc.
+ Copyright 2011, 2012 David Malcolm <dmalcolm(a)redhat.com>
+ Copyright 2011, 2012 Red Hat, Inc.
This is free software: you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
@@ -456,28 +456,53 @@ static PyObject *
gcc_python_warning(PyObject *self, PyObject *args, PyObject *kwargs)
{
PyGccLocation *loc_obj;
- PyGccOption *opt_obj;
const char *msg;
+ PyObject *opt_obj = &_Py_NoneStruct;
+ int opt_code;
char *keywords[] = {"location",
- "option",
"message",
+ "option",
NULL};
bool was_reported;
if (!PyArg_ParseTupleAndKeywords(args, kwargs,
- "O!O!s:warning", keywords,
+ "O!s|O:warning", keywords,
+
+ /* code "O!": */
&gcc_LocationType, &loc_obj,
- &gcc_OptionType, &opt_obj,
- &msg)) {
+ /* code: "s": */
+ &msg,
+
+ /* optional args: */
+ /* code: "O": */
+ &opt_obj)) {
return NULL;
}
- /* Ugly workaround; see this function: */
- if (0 == gcc_python_option_is_enabled(opt_obj->opt_code)) {
- return PyBool_FromLong(0);
+ assert(opt_obj);
+
+ /* If a gcc.Option was given, extract the code: */
+ if (Py_TYPE(opt_obj) == &gcc_OptionType) {
+ opt_code = ((PyGccOption*)opt_obj)->opt_code;
+
+ /* Ugly workaround; see this function: */
+ if (0 == gcc_python_option_is_enabled(opt_code)) {
+ return PyBool_FromLong(0);
+ }
+
+ } else {
+ if (opt_obj == &_Py_NoneStruct) {
+ /* No gcc.Option given: an unconditionally enabled warning: */
+ opt_code = 0;
+ } else {
+ /* Some other object was given: */
+ return PyErr_Format(PyExc_TypeError,
+ ("option must be either None,"
+ " or of type gcc.Option"));
+ }
}
- was_reported = warning_at(loc_obj->loc, opt_obj->opt_code, "%s", msg);
+ was_reported = warning_at(loc_obj->loc, opt_code, "%s", msg);
return PyBool_FromLong(was_reported);
}
diff --git a/tests/plugin/diagnostics/script.py b/tests/plugin/diagnostics/script.py
index 1408616..78968b8 100644
--- a/tests/plugin/diagnostics/script.py
+++ b/tests/plugin/diagnostics/script.py
@@ -15,6 +15,8 @@
# along with this program. If not, see
# <http://www.gnu.org/licenses/>.
+import sys
+
import gcc
# Verify that the various error and warning methods work:
@@ -24,7 +26,8 @@ def on_pass_execution(p, fn):
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, gcc.Option('-Wdiv-by-zero'), 'this is a warning (with positional 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'))
@@ -34,8 +37,24 @@ def on_pass_execution(p, fn):
# Verify that -Wno-format was honored:
gcc.warning(fn.end,
- gcc.Option('-Wformat'),
- 'this warning ought not to appear')
+ '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')
diff --git a/tests/plugin/diagnostics/stderr.txt b/tests/plugin/diagnostics/stderr.txt
index 00da457..77f7cb6 100644
--- a/tests/plugin/diagnostics/stderr.txt
+++ b/tests/plugin/diagnostics/stderr.txt
@@ -4,5 +4,8 @@ tests/plugin/diagnostics/input.c:23:1: error: this is an error (with keyword arg
tests/plugin/diagnostics/input.c:25:1: warning: this is a warning (with positional args) [-Wdiv-by-zero]
tests/plugin/diagnostics/input.c:25:1: warning: this is a warning (with keyword args) [-Wdiv-by-zero]
tests/plugin/diagnostics/input.c:23:1: error: a warning with some embedded format strings %s and %i
+tests/plugin/diagnostics/input.c:25:1: warning: this is an unconditional warning [enabled by default]
+tests/plugin/diagnostics/input.c:25:1: warning: this is another unconditional warning [enabled by default]
+expected error was found: option must be either None, or of type gcc.Option
tests/plugin/diagnostics/input.c:23:1: note: This is the start of the function
tests/plugin/diagnostics/input.c:25:1: note: This is the end of the function
12 years, 5 months