Skip to content

Commit f3e5da2

Browse files
committed
handle variadic function types
Fixes #26
1 parent 33d88ce commit f3e5da2

File tree

7 files changed

+61
-15
lines changed

7 files changed

+61
-15
lines changed

docs/tree.rst

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -585,6 +585,12 @@ Additional attributes for various :py:class:`gcc.Type` subclasses:
585585

586586
The `type` attribute holds the return type.
587587

588+
.. py:attribute:: is_variadic
589+
590+
True if this type represents a variadic function. Note that for
591+
a variadic function, the final `...` argument is not explicitly
592+
represented in `argument_types`.
593+
588594
.. py:attribute:: argument_types
589595
590596
A tuple of :py:class:`gcc.Type` instances, representing the function's

gcc-python-tree.c

Lines changed: 26 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -564,30 +564,19 @@ PyGccFunction_TypeObj_get_argument_types(struct PyGccTree * self, void *closure)
564564

565565
/* Get length of chain */
566566
for (size = 0, iter = head;
567-
iter && iter != error_mark_node;
567+
iter && iter != error_mark_node && iter != void_list_node;
568568
iter = TREE_CHAIN(iter), size++) {
569569
/* empty */
570570
}
571571

572572
/* "size" should now be the length of the chain */
573573

574-
/* The last element in the list is a VOID_TYPE; don't add this;
575-
see dump_function_declaration() in gcc/tree-pretty-print.c */
576-
assert(size>0);
577-
size--;
578-
579574
result = PyTuple_New(size);
580575
if (!result) {
581576
return NULL;
582577
}
583578

584-
/* Iterate, but don't visit the final element: */
585-
for (i = 0, iter = head;
586-
iter && TREE_CHAIN(iter) && iter != error_mark_node;
587-
iter = TREE_CHAIN(iter), i++) {
588-
589-
assert(i<size);
590-
579+
for (i = 0, iter = head; i < size; iter = TREE_CHAIN(iter), i++) {
591580
item = PyGccTree_New(gcc_private_make_tree(TREE_VALUE(iter)));
592581
if (!item) {
593582
goto error;
@@ -605,12 +594,36 @@ PyGccFunction_TypeObj_get_argument_types(struct PyGccTree * self, void *closure)
605594
return NULL;
606595
}
607596

597+
PyObject *
598+
PyGccFunction_TypeObj_is_variadic(struct PyGccTree * self, void *closure)
599+
{
600+
tree iter;
601+
tree head = TYPE_ARG_TYPES(self->t.inner);
602+
603+
/* Get length of chain */
604+
for (iter = head;
605+
iter && iter != error_mark_node && iter != void_list_node;
606+
iter = TREE_CHAIN(iter)) {
607+
/* empty */
608+
}
609+
610+
if (iter == void_list_node)
611+
Py_RETURN_FALSE;
612+
Py_RETURN_TRUE;
613+
}
614+
608615
PyObject *
609616
PyGccMethodType_get_argument_types(struct PyGccTree * self,void *closure)
610617
{
611618
return PyGccFunction_TypeObj_get_argument_types(self, closure);
612619
}
613620

621+
PyObject *
622+
PyGccMethodType_is_variadic(struct PyGccTree * self,void *closure)
623+
{
624+
return PyGccFunction_TypeObj_is_variadic(self, closure);
625+
}
626+
614627
PyObject *
615628
PyGccConstructor_get_elements(PyObject *self, void *closure)
616629
{

gcc-python-wrappers.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -268,6 +268,9 @@ PyGccType_get_sizeof(struct PyGccTree *self, void *closure);
268268
PyObject *
269269
PyGccFunction_TypeObj_get_argument_types(struct PyGccTree * self,void *closure);
270270

271+
PyObject *
272+
PyGccFunction_TypeObj_is_variadic(struct PyGccTree * self, void *closure);
273+
271274
PyObject *
272275
PyGccConstructor_get_elements(PyObject *self, void *closure);
273276

@@ -295,6 +298,9 @@ PyGccIntegerType_repr(struct PyGccTree * self);
295298
PyObject *
296299
PyGccMethodType_get_argument_types(struct PyGccTree * self,void *closure);
297300

301+
PyObject *
302+
PyGccMethodType_is_variadic(struct PyGccTree * self,void *closure);
303+
298304
PyObject *
299305
PyGccStringConstant_repr(struct PyGccTree * self);
300306

generate-tree-c.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -543,12 +543,20 @@ def add_complex_getter(name, doc):
543543
'PyGccFunction_TypeObj_get_argument_types',
544544
None,
545545
"A tuple of gcc.Type instances, representing the argument types of this function type")
546+
getsettable.add_gsdef('is_variadic',
547+
'PyGccFunction_TypeObj_is_variadic',
548+
None,
549+
"Boolean: is this function variadic")
546550

547551
if tree_type.SYM == 'METHOD_TYPE':
548552
getsettable.add_gsdef('argument_types',
549553
'PyGccMethodType_get_argument_types',
550554
None,
551555
"A tuple of gcc.Type instances, representing the argument types of this method type")
556+
getsettable.add_gsdef('is_variadic',
557+
'PyGccMethodType_is_variadic',
558+
None,
559+
"Boolean: is this method variadic")
552560

553561
if tree_type.SYM == 'FUNCTION_DECL':
554562
getsettable.add_gsdef('fullname',

tests/plugin/function-types/input.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,3 +18,5 @@
1818
*/
1919

2020
typedef int (example_fn_type)(char, float);
21+
22+
typedef int (example_variadic_fn_type)(char, float, ...);

tests/plugin/function-types/script.py

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,8 @@
1818
import gcc
1919
import gccutils
2020

21-
def on_finish_unit():
22-
fn_type_decl = gccutils.get_global_typedef('example_fn_type')
21+
def check_fn_type(name):
22+
fn_type_decl = gccutils.get_global_typedef(name)
2323
assert isinstance(fn_type_decl, gcc.TypeDecl)
2424

2525
print('fn_type_decl.name: %r' % fn_type_decl.name)
@@ -30,6 +30,7 @@ def on_finish_unit():
3030
print('str(fn_type.type): %r' % str(fn_type.type))
3131
assert isinstance(fn_type.argument_types, tuple)
3232
print('argument_types: %r' % [str(t) for t in fn_type.argument_types])
33+
print('is_variadic: %r' % fn_type.is_variadic)
3334
try:
3435
fn_type.sizeof
3536
assert 0 # an exception should have been raised
@@ -38,6 +39,9 @@ def on_finish_unit():
3839
print('err: %s' % err)
3940

4041

42+
def on_finish_unit():
43+
check_fn_type('example_fn_type')
44+
check_fn_type('example_variadic_fn_type')
4145

4246
gcc.register_callback(gcc.PLUGIN_FINISH_UNIT,
4347
on_finish_unit)

tests/plugin/function-types/stdout.txt

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,11 @@ fn_type_decl.name: 'example_fn_type'
22
str(fn_type): 'int example_fn_type (char, float)'
33
str(fn_type.type): 'int'
44
argument_types: ['char', 'float']
5+
is_variadic: False
56
err: type "int example_fn_type (char, float)" does not have a "sizeof"
7+
fn_type_decl.name: 'example_variadic_fn_type'
8+
str(fn_type): 'int example_variadic_fn_type (char, float, ...)'
9+
str(fn_type.type): 'int'
10+
argument_types: ['char', 'float']
11+
is_variadic: True
12+
err: type "int example_variadic_fn_type (char, float, ...)" does not have a "sizeof"

0 commit comments

Comments
 (0)