Skip to content

Commit 03b5288

Browse files
committed
gccutils: get pretty-printing working again
* Add new function ``gcc.is_cplusplus`` to determine if we are compiling C++ * Use ``gcc.is_cplusplus`` in gccutils to not iterate over fullname when we are not using C++ (resolves davidmalcolm#72) * Allow accessing ``gcc.Type.sizeof`` to raise a TypeError while pretty-printing to be silently ignored and not added to attributes * Use ``pp_newline_and_flush`` instead of ``pp_newline`` in ``PyGccPrettyPrinter_as_string`` when we are using GCC 5.3 or later (as this provides the historic functionality relied upon)
1 parent c0db474 commit 03b5288

File tree

6 files changed

+47
-14
lines changed

6 files changed

+47
-14
lines changed

docs/versions.rst

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,3 +83,8 @@ On my machine, running this currently gives::
8383
4.8 4008
8484
4.9 4009
8585
=========== ========================
86+
87+
.. py:function:: gcc.is_cplusplus()
88+
:rtype: bool
89+
90+
Determine whether or not we are compiling C++

gcc-python-pretty-printer.c

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,15 @@ PyGccPrettyPrinter_as_string(PyObject *obj)
8888
ppobj = (struct PyGccPrettyPrinter *)obj;
8989

9090
/* Flush the pp first. This forcibly adds a trailing newline: */
91+
#if (GCC_VERSION < 5003)
9192
pp_flush(&ppobj->pp);
93+
#else
94+
/*
95+
* pp_newline_and_flush provides the same functionality on GCC 5.3
96+
* and later
97+
*/
98+
pp_newline_and_flush(&ppobj->pp);
99+
#endif
92100

93101
/* Convert to a python string, leaving off the trailing newline: */
94102
len = strlen(ppobj->buf);

gcc-python-tree.c

Lines changed: 0 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -47,19 +47,6 @@ extern PyGccWrapperTypeObject PyGccIntegerCst_TypeObj;
4747

4848
__typeof__ (lang_check_failed) lang_check_failed __attribute__ ((weak));
4949

50-
51-
/*
52-
Unfortunately, decl_as_string() is only available from the C++
53-
frontend: cc1plus (it's defined in gcc/cp/error.c).
54-
55-
See http://gcc.gnu.org/ml/gcc/2011-11/msg00504.html
56-
57-
Hence we redeclare the symbol as weak, and then check its definition
58-
against 0 before using it.
59-
*/
60-
61-
__typeof__ (decl_as_string) decl_as_string __attribute__ ((weak));
62-
6350
/* Similar for namespace_binding, though gcc 8's r247654 (aka
6451
f906dcc33dd818b71e16c88cef38f33c161070db) replaced it with
6552
get_namespace_value and reversed the order of the params

gcc-python.c

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -401,6 +401,12 @@ PyGcc_get_is_lto(PyObject *self, PyObject *noargs)
401401
return PyBool_FromLong(in_lto_p);
402402
}
403403

404+
static PyObject *
405+
PyGcc_get_is_cplusplus(PyObject *self, PyObject *noargs)
406+
{
407+
return PyBool_FromLong(decl_as_string != NULL);
408+
}
409+
404410
static PyMethodDef GccMethods[] = {
405411
{"register_attribute",
406412
(PyCFunction)PyGcc_RegisterAttribute,
@@ -491,6 +497,9 @@ static PyMethodDef GccMethods[] = {
491497
{"is_lto", PyGcc_get_is_lto, METH_NOARGS,
492498
"Determine whether or not we're being invoked during link-time optimization"},
493499

500+
{"is_cplusplus", PyGcc_get_is_cplusplus, METH_NOARGS,
501+
"Determine whether or not we're compiling C++"},
502+
494503
/* Garbage collection */
495504
{"_force_garbage_collection", PyGcc__force_garbage_collection, METH_NOARGS,
496505
"Forcibly trigger a single run of GCC's garbage collector"},

gcc-python.h

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@
3939
#include "params.h"
4040
#endif
4141
#include "gcc-c-api/gcc-cfg.h"
42+
#include "cp/cp-tree.h" /* for decl_as_string */
4243

4344
/* GCC doesn't seem to give us an ID for "invalid event", so invent one: */
4445
#define GCC_PYTHON_PLUGIN_BAD_EVENT (0xffff)
@@ -69,6 +70,18 @@
6970
#define CPYCHECKER_TYPE_OBJECT_FOR_TYPEDEF(typename)
7071
#endif
7172

73+
/*
74+
Unfortunately, decl_as_string() is only available from the C++
75+
frontend: cc1plus (it's defined in gcc/cp/error.c).
76+
77+
See http://gcc.gnu.org/ml/gcc/2011-11/msg00504.html
78+
79+
Hence we redeclare the symbol as weak, and then check its definition
80+
against 0 before using it.
81+
*/
82+
83+
__typeof__ (decl_as_string) decl_as_string __attribute__ ((weak));
84+
7285
/*
7386
PyObject shared header for wrapping GCC objects, for integration
7487
with GCC's garbage collector (so that things we wrap don't get collected

gccutils/__init__.py

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -148,7 +148,18 @@ def iter_tree_attrs(self, obj):
148148
# Ignore private and "magic" attributes:
149149
if name.startswith('_'):
150150
continue
151-
value = getattr(obj, name)
151+
if (isinstance(obj, gcc.FunctionDecl)
152+
and name == 'fullname'
153+
and not gcc.is_cplusplus()):
154+
continue
155+
try:
156+
value = getattr(obj, name)
157+
except TypeError as e:
158+
# for gcc.Type, sizeof is not always defined, and
159+
# TypeError is raise under this condition
160+
if not isinstance(obj, gcc.Type) or name != 'sizeof':
161+
raise e
162+
continue
152163
# Ignore methods:
153164
if hasattr(value, '__call__'):
154165
continue

0 commit comments

Comments
 (0)