new alloc_size_ex attribute

Hi,

Right now we have support for parsing the alloc_size attribute (introduced in GCC 4.3). This attribute specifies that a given function allocates x bytes, where x is given by the multiplication of the specified parameters.
However, this syntax is still too restrictive for many custom allocation functions I've seen in the wild. Therefore I propose a new attribute: alloc_size_ex (or whatever name we come up with). For the best of my knowledge, GCC doesn't have an equivalent attribute.

examples:
char *my_strdup(char *str) __attribute__((alloc_size_ex(strlen(str)+1)));
void *my_complex_alloc(int n, int size, int add) __attribute__((alloc_size_ex(n * size + add)));
char *middle(int size) __attribute__((alloc_size_ex(size, size/2)));

So the idea is that the first parameter of the attribute is an expression that computes the size of the allocated buffer, and the second (optional) argument gives the offset from the beginning of the buffer. (The remaining bytes that can be read are given by size-offset if offset <= size).
I would suggest the expression's variables to be restricted to the variables used in the call expression.

The second point is how to implement this thing. Right now, clang doesn't allow expressions as attribute's parameters. Can the parser be extended accordingly?
For the codegen side, LLVM already has metadata to support this advanced buffer size information. However, one needs to synthesize a function from the expressions given for the size and offset of the buffer.

Any comments/suggestions/etc..?

Thanks,
Nuno

Right now we have support for parsing the alloc_size attribute
(introduced in GCC 4.3). This attribute specifies that a given
function allocates x bytes, where x is given by the multiplication of
the specified parameters.
However, this syntax is still too restrictive for many custom
allocation functions I've seen in the wild. Therefore I propose a new
attribute: alloc_size_ex (or whatever name we come up with). For the
best of my knowledge, GCC doesn't have an equivalent attribute.

examples:
char *my_strdup(char *str) __attribute__((alloc_size_ex(strlen(str)+1)));
void *my_complex_alloc(int n, int size, int add)
__attribute__((alloc_size_ex(n * size + add)));
char *middle(int size) __attribute__((alloc_size_ex(size, size/2)));

So the idea is that the first parameter of the attribute is an
expression that computes the size of the allocated buffer, and the
second (optional) argument gives the offset from the beginning of the
buffer. (The remaining bytes that can be read are given by size-offset
if offset <= size).
I would suggest the expression's variables to be restricted to the
variables used in the call expression.

This seems like a useful feature to me. What restrictions do you place
on the attribute's expression? Is it required to be a constant
expression? Is it permitted to have side-effects? If not, do you have
a mechanism in mind to check that? Given that Expr::HasSideEffects
doesn't know about strlen (etc.), this part may be tricky.

The second point is how to implement this thing. Right now, clang
doesn't allow expressions as attribute's parameters. Can the parser be
extended accordingly?

Take a look at the thread-safety attributes; they already allow
arbitrary expressions.

Quoting Richard Smith <richard@metafoo.co.uk>:

Right now we have support for parsing the alloc_size attribute
(introduced in GCC 4.3). This attribute specifies that a given
function allocates x bytes, where x is given by the multiplication of
the specified parameters.
However, this syntax is still too restrictive for many custom
allocation functions I've seen in the wild. Therefore I propose a new
attribute: alloc_size_ex (or whatever name we come up with). For the
best of my knowledge, GCC doesn't have an equivalent attribute.

examples:
char *my_strdup(char *str) __attribute__((alloc_size_ex(strlen(str)+1)));
void *my_complex_alloc(int n, int size, int add)
__attribute__((alloc_size_ex(n * size + add)));
char *middle(int size) __attribute__((alloc_size_ex(size, size/2)));

So the idea is that the first parameter of the attribute is an
expression that computes the size of the allocated buffer, and the
second (optional) argument gives the offset from the beginning of the
buffer. (The remaining bytes that can be read are given by size-offset
if offset <= size).
I would suggest the expression's variables to be restricted to the
variables used in the call expression.

This seems like a useful feature to me. What restrictions do you place
on the attribute's expression? Is it required to be a constant
expression? Is it permitted to have side-effects? If not, do you have
a mechanism in mind to check that? Given that Expr::HasSideEffects
doesn't know about strlen (etc.), this part may be tricky.

No, side-effects are not allowed. My idea was to allow only calls to readonly/readnone functions (AFAIR, pure/const in C parlance).

The second point is how to implement this thing. Right now, clang
doesn't allow expressions as attribute's parameters. Can the parser be
extended accordingly?

Take a look at the thread-safety attributes; they already allow
arbitrary expressions.

Ok, great!

Thanks,
Nuno