Skip to content

Commit e3cdf2f

Browse files
committed
Add gcc.RichLocation
1 parent ddb7cc9 commit e3cdf2f

File tree

9 files changed

+196
-19
lines changed

9 files changed

+196
-19
lines changed

docs/diagnostics.rst

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -113,11 +113,12 @@ Generating custom errors and warnings
113113

114114
Returns True if the warning was actually printed, False otherwise
115115

116-
.. py:function:: gcc.inform(loc, str)
116+
.. py:function:: gcc.inform(location, message)
117117
118118
This is a wrapper around GCC's `inform` function.
119119

120-
Expects an instance of :py:class:`gcc.Location` (not None) and a string
120+
Expects an instance of :py:class:`gcc.Location` or
121+
:py:class:`gcc.RichLocation`, (not None) and a string
121122

122123
Emit an informational message at that location.
123124

docs/locations.rst

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,3 +59,13 @@ Locations
5959
# Don't report on issues found in system headers:
6060
if decl.location.in_system_header:
6161
return
62+
63+
.. py:class:: gcc.RichLocation
64+
65+
Wrapper around GCC's `rich_location`, representing one or more locations
66+
within the source code, and zero or more fix-it hints.
67+
68+
.. method:: add_fixit_replace(self, new_content)
69+
70+
Add a fix-it hint, suggesting replacement of the content covered
71+
by range 0 of the rich location with new_content.

gcc-python-diagnostics.c

Lines changed: 19 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
/*
2-
Copyright 2011, 2012, 2013 David Malcolm <dmalcolm@redhat.com>
3-
Copyright 2011, 2012, 2013 Red Hat, Inc.
2+
Copyright 2011-2013, 2017 David Malcolm <dmalcolm@redhat.com>
3+
Copyright 2011-2013, 2017 Red Hat, Inc.
44
55
This is free software: you can redistribute it and/or modify it
66
under the terms of the GNU General Public License as published by
@@ -144,22 +144,32 @@ PyGcc_warning(PyObject *self, PyObject *args, PyObject *kwargs)
144144
PyObject *
145145
PyGcc_inform(PyObject *self, PyObject *args, PyObject *kwargs)
146146
{
147-
PyGccLocation *loc_obj;
147+
PyObject *obj;
148148
const char *msg;
149149
const char *keywords[] = {"location",
150150
"message",
151151
NULL};
152152

153153
if (!PyArg_ParseTupleAndKeywords(args, kwargs,
154-
"O!s:inform", (char**)keywords,
155-
&PyGccLocation_TypeObj, &loc_obj,
156-
&msg)) {
154+
"Os:inform", (char**)keywords,
155+
&obj, &msg)) {
157156
return NULL;
158157
}
159158

160-
gcc_inform(loc_obj->loc, msg);
161-
162-
Py_RETURN_NONE;
159+
/* Check for location vs rich_location. */
160+
if (Py_TYPE (obj) == (PyTypeObject *)&PyGccLocation_TypeObj) {
161+
PyGccLocation *loc_obj = (PyGccLocation *)obj;
162+
gcc_inform(loc_obj->loc, msg);
163+
Py_RETURN_NONE;
164+
} else if (Py_TYPE (obj) == (PyTypeObject *)&PyGccRichLocation_TypeObj) {
165+
PyGccRichLocation *richloc_obj = (PyGccRichLocation *)obj;
166+
inform_at_rich_loc (&richloc_obj->richloc, msg);
167+
Py_RETURN_NONE;
168+
} else {
169+
return PyErr_Format(PyExc_TypeError,
170+
("type of location must be either gcc.Location"
171+
" or gcc.RichLocation"));
172+
}
163173
}
164174

165175
/*

gcc-python-location.c

Lines changed: 46 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
/*
2-
Copyright 2011, 2012, 2013 David Malcolm <dmalcolm@redhat.com>
3-
Copyright 2011, 2012, 2013 Red Hat, Inc.
2+
Copyright 2011-2013, 2017 David Malcolm <dmalcolm@redhat.com>
3+
Copyright 2011-2013, 2017 Red Hat, Inc.
44
55
This is free software: you can redistribute it and/or modify it
66
under the terms of the GNU General Public License as published by
@@ -193,6 +193,50 @@ PyGcc_WrtpMarkForPyGccLocation(PyGccLocation *wrapper)
193193
/* empty */
194194
}
195195

196+
/* rich_location. */
197+
198+
PyObject *
199+
PyGccRichLocation_add_fixit_replace(PyGccRichLocation *self, PyObject *args,
200+
PyObject *kwargs)
201+
{
202+
const char *keywords[] = {"new_content",
203+
NULL};
204+
const char *new_content;
205+
206+
if (!PyArg_ParseTupleAndKeywords(args, kwargs,
207+
"s", (char**)keywords,
208+
&new_content)) {
209+
return NULL;
210+
}
211+
212+
self->richloc.add_fixit_replace (new_content);
213+
214+
Py_RETURN_NONE;
215+
}
216+
217+
int
218+
PyGccRichLocation_init(PyGccRichLocation *self, PyObject *args,
219+
PyObject *kwargs)
220+
{
221+
const char *keywords[] = {"location",
222+
NULL};
223+
PyGccLocation *loc_obj;
224+
225+
if (!PyArg_ParseTupleAndKeywords(args, kwargs,
226+
"O!", (char**)keywords,
227+
&PyGccLocation_TypeObj, &loc_obj)) {
228+
return -1;
229+
}
230+
// FIXME: also need a manual dtor call
231+
new (&self->richloc) rich_location (line_table, loc_obj->loc.inner);
232+
return 0;
233+
}
234+
235+
void
236+
PyGcc_WrtpMarkForPyGccRichLocation(PyGccRichLocation *wrapper)
237+
{
238+
/* empty */
239+
}
196240

197241
/*
198242
PEP-7

gcc-python-wrappers.h

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
/*
2-
Copyright 2011-2013, 2015 David Malcolm <dmalcolm@redhat.com>
3-
Copyright 2011-2013, 2015 Red Hat, Inc.
2+
Copyright 2011-2013, 2015, 2017 David Malcolm <dmalcolm@redhat.com>
3+
Copyright 2011-2013, 2015, 2017 Red Hat, Inc.
44
55
This is free software: you can redistribute it and/or modify it
66
under the terms of the GNU General Public License as published by
@@ -144,6 +144,14 @@ PyGccLocation_richcompare(PyObject *o1, PyObject *o2, int op);
144144
long
145145
PyGccLocation_hash(struct PyGccLocation * self);
146146

147+
PyObject *
148+
PyGccRichLocation_add_fixit_replace(PyGccRichLocation *self, PyObject *args,
149+
PyObject *kwargs);
150+
151+
int
152+
PyGccRichLocation_init(PyGccRichLocation *self, PyObject *args,
153+
PyObject *kwargs);
154+
147155
/* gcc-python-cfg.c: */
148156
PyObject *
149157
PyGccBasicBlock_repr(struct PyGccBasicBlock * self);

gcc-python.h

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
/*
2-
Copyright 2011-2013, 2015 David Malcolm <dmalcolm@redhat.com>
3-
Copyright 2011-2013, 2015 Red Hat, Inc.
2+
Copyright 2011-2013, 2015, 2017 David Malcolm <dmalcolm@redhat.com>
3+
Copyright 2011-2013, 2015, 2017 Red Hat, Inc.
44
55
This is free software: you can redistribute it and/or modify it
66
under the terms of the GNU General Public License as published by
@@ -185,6 +185,11 @@ DECLARE_SIMPLE_WRAPPER(PyGccLocation,
185185
location,
186186
gcc_location, loc)
187187

188+
DECLARE_SIMPLE_WRAPPER(PyGccRichLocation,
189+
PyGccRichLocation_TypeObj,
190+
rich_location,
191+
rich_location, richloc)
192+
188193
DECLARE_SIMPLE_WRAPPER(PyGccGimple,
189194
PyGccGimple_TypeObj,
190195
gimple,

generate-location-c.py

Lines changed: 34 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
# Copyright 2011, 2012, 2013, 2014 David Malcolm <dmalcolm@redhat.com>
2-
# Copyright 2011, 2012, 2013, 2014 Red Hat, Inc.
1+
# Copyright 2011-2014, 2017 David Malcolm <dmalcolm@redhat.com>
2+
# Copyright 2011-2014, 2017 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
@@ -90,7 +90,39 @@ def generate_location():
9090
modinit_preinit += pytype.c_invoke_type_ready()
9191
modinit_postinit += pytype.c_invoke_add_to_module()
9292

93+
def generate_rich_location():
94+
#
95+
# Generate the gcc.RichLocation class:
96+
#
97+
global modinit_preinit
98+
global modinit_postinit
99+
100+
methods = PyMethodTable('PyGccRichLocation_methods', [])
101+
methods.add_method('add_fixit_replace',
102+
'(PyCFunction)PyGccRichLocation_add_fixit_replace',
103+
'METH_VARARGS | METH_KEYWORDS',
104+
"FIXME")
105+
cu.add_defn(methods.c_defn())
106+
107+
pytype = PyGccWrapperTypeObject(identifier = 'PyGccRichLocation_TypeObj',
108+
localname = 'RichLocation',
109+
tp_name = 'gcc.RichLocation',
110+
struct_name = 'PyGccRichLocation',
111+
tp_new = 'PyType_GenericNew',
112+
tp_init = '(initproc)PyGccRichLocation_init',
113+
#tp_getset = getsettable.identifier,
114+
#tp_hash = '(hashfunc)PyGccRichLocation_hash',
115+
#tp_repr = '(reprfunc)PyGccRichLocation_repr',
116+
#tp_str = '(reprfunc)PyGccRichLocation_str',
117+
tp_methods = methods.identifier,
118+
#tp_richcompare = 'PyGccRichLocation_richcompare',
119+
tp_dealloc = 'PyGccWrapper_Dealloc')
120+
cu.add_defn(pytype.c_defn())
121+
modinit_preinit += pytype.c_invoke_type_ready()
122+
modinit_postinit += pytype.c_invoke_add_to_module()
123+
93124
generate_location()
125+
generate_rich_location()
94126

95127
cu.add_defn("""
96128
int autogenerated_location_init_types(void)

tests/plugin/rich-location/input.c

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
/*
2+
Copyright 2017 David Malcolm <dmalcolm@redhat.com>
3+
Copyright 2017 Red Hat, Inc.
4+
5+
This is free software: you can redistribute it and/or modify it
6+
under the terms of the GNU General Public License as published by
7+
the Free Software Foundation, either version 3 of the License, or
8+
(at your option) any later version.
9+
10+
This program is distributed in the hope that it will be useful, but
11+
WITHOUT ANY WARRANTY; without even the implied warranty of
12+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13+
General Public License for more details.
14+
15+
You should have received a copy of the GNU General Public License
16+
along with this program. If not, see
17+
<http://www.gnu.org/licenses/>.
18+
*/
19+
20+
/* { dg-do compile } */
21+
22+
void test_1 (void)
23+
{ /* { dg-message "1: this is the start of the function" } */
24+
} /* { dg-message "1: this is the end of the function" } */
25+
26+
/*
27+
PEP-7
28+
Local variables:
29+
c-basic-offset: 4
30+
indent-tabs-mode: nil
31+
End:
32+
*/
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
# Copyright 2017 David Malcolm <dmalcolm@redhat.com>
2+
# Copyright 2017 Red Hat, Inc.
3+
#
4+
# This is free software: you can redistribute it and/or modify it
5+
# under the terms of the GNU General Public License as published by
6+
# the Free Software Foundation, either version 3 of the License, or
7+
# (at your option) any later version.
8+
#
9+
# This program is distributed in the hope that it will be useful, but
10+
# WITHOUT ANY WARRANTY; without even the implied warranty of
11+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12+
# General Public License for more details.
13+
#
14+
# You should have received a copy of the GNU General Public License
15+
# along with this program. If not, see
16+
# <http://www.gnu.org/licenses/>.
17+
18+
import sys
19+
20+
import gcc
21+
22+
# Verify that the various error and warning methods work:
23+
24+
def on_pass_execution(p, fn):
25+
if p.name == '*warn_function_return':
26+
# Exercise gcc.inform with gcc.RichLocation:
27+
gcc.inform(gcc.RichLocation(fn.start),
28+
'this is the start of the function')
29+
gcc.inform(gcc.RichLocation(fn.end),
30+
'this is the end of the function')
31+
32+
# Wire up our callback:
33+
gcc.register_callback(gcc.PLUGIN_PASS_EXECUTION,
34+
on_pass_execution)
35+

0 commit comments

Comments
 (0)