Skip to content

handle variadic function types #32

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Nov 20, 2015
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions docs/tree.rst
Original file line number Diff line number Diff line change
Expand Up @@ -585,6 +585,12 @@ Additional attributes for various :py:class:`gcc.Type` subclasses:

The `type` attribute holds the return type.

.. py:attribute:: is_variadic

True if this type represents a variadic function. Note that for
a variadic function, the final `...` argument is not explicitly
represented in `argument_types`.

.. py:attribute:: argument_types

A tuple of :py:class:`gcc.Type` instances, representing the function's
Expand Down
39 changes: 26 additions & 13 deletions gcc-python-tree.c
Original file line number Diff line number Diff line change
Expand Up @@ -564,30 +564,19 @@ PyGccFunction_TypeObj_get_argument_types(struct PyGccTree * self, void *closure)

/* Get length of chain */
for (size = 0, iter = head;
iter && iter != error_mark_node;
iter && iter != error_mark_node && iter != void_list_node;
iter = TREE_CHAIN(iter), size++) {
/* empty */
}

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

/* The last element in the list is a VOID_TYPE; don't add this;
see dump_function_declaration() in gcc/tree-pretty-print.c */
assert(size>0);
size--;

result = PyTuple_New(size);
if (!result) {
return NULL;
}

/* Iterate, but don't visit the final element: */
for (i = 0, iter = head;
iter && TREE_CHAIN(iter) && iter != error_mark_node;
iter = TREE_CHAIN(iter), i++) {

assert(i<size);

for (i = 0, iter = head; i < size; iter = TREE_CHAIN(iter), i++) {
item = PyGccTree_New(gcc_private_make_tree(TREE_VALUE(iter)));
if (!item) {
goto error;
Expand All @@ -605,12 +594,36 @@ PyGccFunction_TypeObj_get_argument_types(struct PyGccTree * self, void *closure)
return NULL;
}

PyObject *
PyGccFunction_TypeObj_is_variadic(struct PyGccTree * self, void *closure)
{
tree iter;
tree head = TYPE_ARG_TYPES(self->t.inner);

/* Get length of chain */
for (iter = head;
iter && iter != error_mark_node && iter != void_list_node;
iter = TREE_CHAIN(iter)) {
/* empty */
}

if (iter == void_list_node)
Py_RETURN_FALSE;
Py_RETURN_TRUE;
}

PyObject *
PyGccMethodType_get_argument_types(struct PyGccTree * self,void *closure)
{
return PyGccFunction_TypeObj_get_argument_types(self, closure);
}

PyObject *
PyGccMethodType_is_variadic(struct PyGccTree * self,void *closure)
{
return PyGccFunction_TypeObj_is_variadic(self, closure);
}

PyObject *
PyGccConstructor_get_elements(PyObject *self, void *closure)
{
Expand Down
6 changes: 6 additions & 0 deletions gcc-python-wrappers.h
Original file line number Diff line number Diff line change
Expand Up @@ -268,6 +268,9 @@ PyGccType_get_sizeof(struct PyGccTree *self, void *closure);
PyObject *
PyGccFunction_TypeObj_get_argument_types(struct PyGccTree * self,void *closure);

PyObject *
PyGccFunction_TypeObj_is_variadic(struct PyGccTree * self, void *closure);

PyObject *
PyGccConstructor_get_elements(PyObject *self, void *closure);

Expand Down Expand Up @@ -295,6 +298,9 @@ PyGccIntegerType_repr(struct PyGccTree * self);
PyObject *
PyGccMethodType_get_argument_types(struct PyGccTree * self,void *closure);

PyObject *
PyGccMethodType_is_variadic(struct PyGccTree * self,void *closure);

PyObject *
PyGccStringConstant_repr(struct PyGccTree * self);

Expand Down
8 changes: 8 additions & 0 deletions generate-tree-c.py
Original file line number Diff line number Diff line change
Expand Up @@ -543,12 +543,20 @@ def add_complex_getter(name, doc):
'PyGccFunction_TypeObj_get_argument_types',
None,
"A tuple of gcc.Type instances, representing the argument types of this function type")
getsettable.add_gsdef('is_variadic',
'PyGccFunction_TypeObj_is_variadic',
None,
"Boolean: is this function variadic")

if tree_type.SYM == 'METHOD_TYPE':
getsettable.add_gsdef('argument_types',
'PyGccMethodType_get_argument_types',
None,
"A tuple of gcc.Type instances, representing the argument types of this method type")
getsettable.add_gsdef('is_variadic',
'PyGccMethodType_is_variadic',
None,
"Boolean: is this method variadic")

if tree_type.SYM == 'FUNCTION_DECL':
getsettable.add_gsdef('fullname',
Expand Down
2 changes: 2 additions & 0 deletions tests/plugin/function-types/input.c
Original file line number Diff line number Diff line change
Expand Up @@ -18,3 +18,5 @@
*/

typedef int (example_fn_type)(char, float);

typedef int (example_variadic_fn_type)(char, float, ...);
8 changes: 6 additions & 2 deletions tests/plugin/function-types/script.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,8 @@
import gcc
import gccutils

def on_finish_unit():
fn_type_decl = gccutils.get_global_typedef('example_fn_type')
def check_fn_type(name):
fn_type_decl = gccutils.get_global_typedef(name)
assert isinstance(fn_type_decl, gcc.TypeDecl)

print('fn_type_decl.name: %r' % fn_type_decl.name)
Expand All @@ -30,6 +30,7 @@ def on_finish_unit():
print('str(fn_type.type): %r' % str(fn_type.type))
assert isinstance(fn_type.argument_types, tuple)
print('argument_types: %r' % [str(t) for t in fn_type.argument_types])
print('is_variadic: %r' % fn_type.is_variadic)
try:
fn_type.sizeof
assert 0 # an exception should have been raised
Expand All @@ -38,6 +39,9 @@ def on_finish_unit():
print('err: %s' % err)


def on_finish_unit():
check_fn_type('example_fn_type')
check_fn_type('example_variadic_fn_type')

gcc.register_callback(gcc.PLUGIN_FINISH_UNIT,
on_finish_unit)
7 changes: 7 additions & 0 deletions tests/plugin/function-types/stdout.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,11 @@ fn_type_decl.name: 'example_fn_type'
str(fn_type): 'int example_fn_type (char, float)'
str(fn_type.type): 'int'
argument_types: ['char', 'float']
is_variadic: False
err: type "int example_fn_type (char, float)" does not have a "sizeof"
fn_type_decl.name: 'example_variadic_fn_type'
str(fn_type): 'int example_variadic_fn_type (char, float, ...)'
str(fn_type.type): 'int'
argument_types: ['char', 'float']
is_variadic: True
err: type "int example_variadic_fn_type (char, float, ...)" does not have a "sizeof"