Skip to content

Commit 5f7ea44

Browse files
committed
Avoid multiline warning strings in libcpychecker.formatstrings
When building with gcc 6, warnings emitted by libcpychecker.formatstrings.WrongNumberOfVars showed some whitespace differences in the final " [-Werror]": ERROR: test_too_many_varargs (__main__.PyArg_ParseTupleAndKeywordsTests) - [-Werror] + [-Werror] I'm not sure exactly why this has started, but it seems error-prone to be sending multiline strings through warning_at, so this patch standardizes these warnings to emit just one line for the warning_at, and then print the additional information to stderr via extra_info (), generalizing the approach already used by MismatchingType.
1 parent 3a5add3 commit 5f7ea44

File tree

3 files changed

+32
-31
lines changed

3 files changed

+32
-31
lines changed

libcpychecker/formatstrings.py

Lines changed: 22 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
# Copyright 2011 David Malcolm <dmalcolm@redhat.com>
2-
# Copyright 2011 Red Hat, Inc.
1+
# Copyright 2011, 2016 David Malcolm <dmalcolm@redhat.com>
2+
# Copyright 2011, 2016 Red Hat, Inc.
33
#
44
# This is free software: you can redistribute it and/or modify it
55
# under the terms of the GNU General Public License as published by
@@ -58,6 +58,13 @@ class FormatStringWarning(CExtensionWarning):
5858
def __init__(self, fmt_string):
5959
self.fmt_string = fmt_string
6060

61+
def emit_as_warning(self, loc):
62+
if gcc.warning(loc, str(self)):
63+
sys.stderr.write(self.extra_info())
64+
65+
def extra_info(self):
66+
return ""
67+
6168
class UnknownFormatChar(FormatStringWarning):
6269
def __init__(self, fmt_string, ch):
6370
FormatStringWarning.__init__(self, fmt_string)
@@ -137,12 +144,14 @@ def __init__(self, funcname, fmt, varargs):
137144
self.varargs = varargs
138145

139146
def __str__(self):
140-
result = ('%s in call to %s with format string "%s"\n'
141-
' expected %i extra arguments:\n'
142-
% (self._get_desc_prefix(),
143-
self.funcname,
144-
self.fmt.fmt_string,
145-
self.fmt.num_expected()))
147+
return ('%s in call to %s with format string "%s"'
148+
% (self._get_desc_prefix(),
149+
self.funcname,
150+
self.fmt.fmt_string))
151+
152+
def extra_info(self):
153+
result = (' expected %i extra arguments:\n'
154+
% self.fmt.num_expected())
146155
for (arg, exp_type) in self.fmt.iter_exp_types():
147156
result += ' %s\n' % describe_type(exp_type)
148157
if len(self.varargs) == 0:
@@ -380,8 +389,8 @@ def check_callsite(stmt, parser, funcname, format_idx, varargs_idx, with_size_t)
380389
try:
381390
fmt = parser.from_string(fmt_string, with_size_t)
382391
except FormatStringWarning:
383-
exc = sys.exc_info()[1]
384-
gcc.warning(stmt.loc, str(exc))
392+
err = sys.exc_info()[1]
393+
err.emit_as_warning(stmt.loc)
385394
return
386395
log('fmt: %r', fmt.args)
387396

@@ -392,11 +401,11 @@ def check_callsite(stmt, parser, funcname, format_idx, varargs_idx, with_size_t)
392401
varargs = stmt.args[varargs_idx:]
393402
# log('varargs: %r', varargs)
394403
if len(varargs) < len(exp_types):
395-
gcc.warning(loc, str(NotEnoughVars(funcname, fmt, varargs)))
404+
NotEnoughVars(funcname, fmt, varargs).emit_as_warning(loc)
396405
return
397406

398407
if len(varargs) > len(exp_types):
399-
gcc.warning(loc, str(TooManyVars(funcname, fmt, varargs)))
408+
TooManyVars(funcname, fmt, varargs).emit_as_warning(loc)
400409
return
401410

402411
for index, ((exp_arg, exp_type), vararg) in enumerate(zip(exp_types, varargs)):
@@ -408,9 +417,7 @@ def check_callsite(stmt, parser, funcname, format_idx, varargs_idx, with_size_t)
408417
loc = vararg.location
409418
else:
410419
loc = stmt.loc
411-
gcc.warning(loc,
412-
str(err))
413-
sys.stderr.write(err.extra_info())
420+
err.emit_as_warning(loc)
414421

415422
def maybe_check_callsite(stmt):
416423
if stmt.fndecl:

testcpychecker.py

Lines changed: 8 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -182,11 +182,10 @@ def test_not_enough_varargs(self):
182182
"""
183183
self.assertFindsError(src,
184184
"$(SRCFILE): In function 'not_enough_varargs':\n"
185-
'$(SRCFILE):13:25: error: Not enough arguments in call to PyArg_ParseTuple with format string "i"\n'
185+
'$(SRCFILE):13:25: error: Not enough arguments in call to PyArg_ParseTuple with format string "i" [-Werror]\n'
186186
' expected 1 extra arguments:\n'
187187
' "int *" (pointing to 32 bits)\n'
188-
' but got none\n'
189-
' [-Werror]\n')
188+
' but got none\n')
190189

191190
def test_too_many_varargs(self):
192191
src = """
@@ -202,13 +201,12 @@ def test_too_many_varargs(self):
202201
"""
203202
self.assertFindsError(src,
204203
"$(SRCFILE): In function 'too_many_varargs':\n"
205-
'$(SRCFILE):14:26: error: Too many arguments in call to PyArg_ParseTuple with format string "i"\n'
204+
'$(SRCFILE):14:26: error: Too many arguments in call to PyArg_ParseTuple with format string "i" [-Werror]\n'
206205
' expected 1 extra arguments:\n'
207206
' "int *" (pointing to 32 bits)\n'
208207
' but got 2:\n'
209208
' "int *" (pointing to 32 bits)\n'
210-
' "int *" (pointing to 32 bits)\n'
211-
' [-Werror]\n')
209+
' "int *" (pointing to 32 bits)\n')
212210

213211
def test_correct_usage(self):
214212
src = """
@@ -528,11 +526,10 @@ def test_not_enough_varargs(self):
528526
"""
529527
self.assertFindsError(src,
530528
"$(SRCFILE): In function 'not_enough_varargs':\n"
531-
'$(SRCFILE):13:5: error: Not enough arguments in call to Py_BuildValue with format string "i"\n'
529+
'$(SRCFILE):13:5: error: Not enough arguments in call to Py_BuildValue with format string "i" [-Werror]\n'
532530
' expected 1 extra arguments:\n'
533531
' "int"\n'
534-
' but got none\n'
535-
' [-Werror]\n')
532+
' but got none\n')
536533

537534
def test_too_many_varargs(self):
538535
src = """
@@ -544,13 +541,12 @@ def test_too_many_varargs(self):
544541
"""
545542
self.assertFindsError(src,
546543
"$(SRCFILE): In function 'too_many_varargs':\n"
547-
'$(SRCFILE):13:5: error: Too many arguments in call to Py_BuildValue with format string "i"\n'
544+
'$(SRCFILE):13:5: error: Too many arguments in call to Py_BuildValue with format string "i" [-Werror]\n'
548545
' expected 1 extra arguments:\n'
549546
' "int"\n'
550547
' but got 2:\n'
551548
' "int"\n'
552-
' "int"\n'
553-
' [-Werror]\n')
549+
' "int"\n')
554550

555551
def test_correct_usage(self):
556552
src = """

tests/cpychecker/PyArg_ParseTuple/incorrect_converters/stderr.txt

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,15 @@
11
In function 'incorrect_usages_of_converter':
2-
tests/cpychecker/PyArg_ParseTuple/incorrect_converters/input.c:36:nn: warning: Not enough arguments in call to PyArg_ParseTuple with format string "O&"
2+
tests/cpychecker/PyArg_ParseTuple/incorrect_converters/input.c:36:nn: warning: Not enough arguments in call to PyArg_ParseTuple with format string "O&" [enabled by default]
33
expected 2 extra arguments:
44
"int (converter)(PyObject *, T*)" for some type T
55
"T*" for some type T
66
but got none
7-
[enabled by default]
8-
tests/cpychecker/PyArg_ParseTuple/incorrect_converters/input.c:39:nn: warning: Not enough arguments in call to PyArg_ParseTuple with format string "O&"
7+
tests/cpychecker/PyArg_ParseTuple/incorrect_converters/input.c:39:nn: warning: Not enough arguments in call to PyArg_ParseTuple with format string "O&" [enabled by default]
98
expected 2 extra arguments:
109
"int (converter)(PyObject *, T*)" for some type T
1110
"T*" for some type T
1211
but got 1:
1312
"int"
14-
[enabled by default]
1513
tests/cpychecker/PyArg_ParseTuple/incorrect_converters/input.c:44:nn: warning: Mismatching type in call to PyArg_ParseTuple with format code "O&" [enabled by default]
1614
argument 3 ("42") had type
1715
"int"

0 commit comments

Comments
 (0)