summaryrefslogtreecommitdiff
path: root/gcc/tree-object-size.c
diff options
context:
space:
mode:
authormueller <mueller@138bc75d-0d04-0410-961f-82ee72b054a4>2007-05-25 21:18:15 +0000
committermueller <mueller@138bc75d-0d04-0410-961f-82ee72b054a4>2007-05-25 21:18:15 +0000
commit4a29c97c96f0b3c1d102a225e4da92f2536547fe (patch)
treef9fc57995ca9957ad153664eb76e3a1d3b7c3a41 /gcc/tree-object-size.c
parent9aad947b05a41449783d1cda7d14eb5f97277b55 (diff)
downloadgcc-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.c56
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);