diff options
author | mueller <mueller@138bc75d-0d04-0410-961f-82ee72b054a4> | 2007-05-25 21:18:15 +0000 |
---|---|---|
committer | mueller <mueller@138bc75d-0d04-0410-961f-82ee72b054a4> | 2007-05-25 21:18:15 +0000 |
commit | 4a29c97c96f0b3c1d102a225e4da92f2536547fe (patch) | |
tree | f9fc57995ca9957ad153664eb76e3a1d3b7c3a41 /gcc/tree-object-size.c | |
parent | 9aad947b05a41449783d1cda7d14eb5f97277b55 (diff) | |
download | gcc-4a29c97c96f0b3c1d102a225e4da92f2536547fe.tar.gz |
2007-05-25 Dirk Mueller <dmueller@suse.de>
Marcus Meissner <meissner@suse.de>
* doc/extend.texi (alloc_size): New attribute.
* c-common.c (handle_alloc_size_attribute): New.
* tree-object-size.c (alloc_object_size): Use alloc_size
attribute, if available.
* testsuite/gcc.dg/attr-alloc_size.c: New.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@125073 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/tree-object-size.c')
-rw-r--r-- | gcc/tree-object-size.c | 56 |
1 files changed, 35 insertions, 21 deletions
diff --git a/gcc/tree-object-size.c b/gcc/tree-object-size.c index 1eb09cbc50a..fee75a8e72a 100644 --- a/gcc/tree-object-size.c +++ b/gcc/tree-object-size.c @@ -24,6 +24,7 @@ Boston, MA 02110-1301, USA. */ #include "coretypes.h" #include "tm.h" #include "tree.h" +#include "toplev.h" #include "diagnostic.h" #include "tree-flow.h" #include "tree-pass.h" @@ -229,39 +230,52 @@ static unsigned HOST_WIDE_INT alloc_object_size (tree call, int object_size_type) { tree callee, bytes = NULL_TREE; + tree alloc_size; + int arg1 = -1, arg2 = -1; gcc_assert (TREE_CODE (call) == CALL_EXPR); callee = get_callee_fndecl (call); - if (callee - && DECL_BUILT_IN_CLASS (callee) == BUILT_IN_NORMAL) + if (!callee) + return unknown[object_size_type]; + + alloc_size = lookup_attribute ("alloc_size", TYPE_ATTRIBUTES (TREE_TYPE(callee))); + if (alloc_size && TREE_VALUE (alloc_size)) + { + tree p = TREE_VALUE (alloc_size); + + arg1 = TREE_INT_CST_LOW (TREE_VALUE (p))-1; + if (TREE_CHAIN (p)) + arg2 = TREE_INT_CST_LOW (TREE_VALUE (TREE_CHAIN (p)))-1; + } + + if (DECL_BUILT_IN_CLASS (callee) == BUILT_IN_NORMAL) switch (DECL_FUNCTION_CODE (callee)) { + case BUILT_IN_CALLOC: + arg2 = 1; + /* fall through */ case BUILT_IN_MALLOC: case BUILT_IN_ALLOCA: - if (call_expr_nargs (call) == 1 - && TREE_CODE (CALL_EXPR_ARG (call, 0)) == INTEGER_CST) - bytes = fold_convert (sizetype, CALL_EXPR_ARG (call, 0)); - break; - /* - case BUILT_IN_REALLOC: - if (call_expr_nargs (call) == 2 - && TREE_CODE (CALL_EXPR_ARG (call, 1)) == INTEGER_CST) - bytes = fold_convert (sizetype, CALL_EXPR_ARG (call, 1)); - break; - */ - case BUILT_IN_CALLOC: - if (call_expr_nargs (call) == 2 - && TREE_CODE (CALL_EXPR_ARG (call, 0)) == INTEGER_CST - && TREE_CODE (CALL_EXPR_ARG (call, 1)) == INTEGER_CST) - bytes = size_binop (MULT_EXPR, - fold_convert (sizetype, CALL_EXPR_ARG (call, 0)), - fold_convert (sizetype, CALL_EXPR_ARG (call, 1))); - break; + arg1 = 0; default: break; } + if (arg1 < 0 || arg1 >= call_expr_nargs (call) + || TREE_CODE (CALL_EXPR_ARG (call, arg1)) != INTEGER_CST + || (arg2 >= 0 + && (arg2 >= call_expr_nargs (call) + || TREE_CODE (CALL_EXPR_ARG (call, arg2)) != INTEGER_CST))) + return unknown[object_size_type]; + + if (arg2 >= 0) + bytes = size_binop (MULT_EXPR, + fold_convert (sizetype, CALL_EXPR_ARG (call, arg1)), + fold_convert (sizetype, CALL_EXPR_ARG (call, arg2))); + else if (arg1 >= 0) + bytes = fold_convert (sizetype, CALL_EXPR_ARG (call, arg1)); + if (bytes && host_integerp (bytes, 1)) return tree_low_cst (bytes, 1); |