From 3a60b071609ae5cda7e85eccf206659d3e75c00d Mon Sep 17 00:00:00 2001 From: burnus Date: Sat, 20 Feb 2010 08:31:25 +0000 Subject: [PATCH] 2010-02-20 Tobias Burnus PR fortran/42958 * libgfortran.h: Add GFC_RTCHECK_MEM. * invoke.texi (-fcheck=): Document -fcheck=mem. * tranc.c (gfc_call_malloc): Remove negative-size run-time error and enable malloc-success check only with -fcheck=mem. * option.c (gfc_handle_runtime_check_option): Add -fcheck=mem. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@156923 138bc75d-0d04-0410-961f-82ee72b054a4 --- gcc/fortran/ChangeLog | 9 +++++++++ gcc/fortran/invoke.texi | 8 +++++++- gcc/fortran/libgfortran.h | 3 ++- gcc/fortran/options.c | 5 +++-- gcc/fortran/trans.c | 43 +++++++++++++++++++------------------------ 5 files changed, 40 insertions(+), 28 deletions(-) diff --git a/gcc/fortran/ChangeLog b/gcc/fortran/ChangeLog index db05fd3e3ca..8776bd54d20 100644 --- a/gcc/fortran/ChangeLog +++ b/gcc/fortran/ChangeLog @@ -1,3 +1,12 @@ +2010-02-20 Tobias Burnus + + PR fortran/42958 + * libgfortran.h: Add GFC_RTCHECK_MEM. + * invoke.texi (-fcheck=): Document -fcheck=mem. + * tranc.c (gfc_call_malloc): Remove negative-size run-time error + and enable malloc-success check only with -fcheck=mem. + * option.c (gfc_handle_runtime_check_option): Add -fcheck=mem. + 2010-02-16 Tobias Burnus PR fortran/43040 diff --git a/gcc/fortran/invoke.texi b/gcc/fortran/invoke.texi index 88a395d04d0..9fe75d17b8b 100644 --- a/gcc/fortran/invoke.texi +++ b/gcc/fortran/invoke.texi @@ -166,7 +166,7 @@ and warnings}. @gccoptlist{-fno-automatic -ff2c -fno-underscoring @gol -fwhole-file -fsecond-underscore @gol -fbounds-check -fcheck-array-temporaries -fmax-array-constructor =@var{n} @gol --fcheck=@var{} +-fcheck=@var{} -fmax-stack-var-size=@var{n} @gol -fpack-derived -frepack-arrays -fshort-enums -fexternal-blas @gol -fblas-matmul-limit=@var{n} -frecursive -finit-local-zero @gol @@ -1216,6 +1216,7 @@ by use of the @option{-ff2c} option. @cindex array, bounds checking @cindex bounds checking @cindex pointer checking +@cindex memory checking @cindex range checking @cindex subscript checking @cindex checking subscripts @@ -1254,6 +1255,11 @@ checking substring references. Enable generation of run-time checks for invalid modification of loop iteration variables. +@item @samp{mem} +Enable generation of run-time checks for memory allocation. +Note: This option does not affect explicit allocations using the +@code{ALLOCATE} statement, which will be always checked. + @item @samp{pointer} Enable generation of run-time checks for pointers and allocatables. diff --git a/gcc/fortran/libgfortran.h b/gcc/fortran/libgfortran.h index d66020717a4..c39f54b19fc 100644 --- a/gcc/fortran/libgfortran.h +++ b/gcc/fortran/libgfortran.h @@ -48,9 +48,10 @@ along with GCC; see the file COPYING3. If not see #define GFC_RTCHECK_RECURSION (1<<2) #define GFC_RTCHECK_DO (1<<3) #define GFC_RTCHECK_POINTER (1<<4) +#define GFC_RTCHECK_MEM (1<<5) #define GFC_RTCHECK_ALL (GFC_RTCHECK_BOUNDS | GFC_RTCHECK_ARRAY_TEMPS \ | GFC_RTCHECK_RECURSION | GFC_RTCHECK_DO \ - | GFC_RTCHECK_POINTER) + | GFC_RTCHECK_POINTER | GFC_RTCHECK_MEM) /* Possible values for the CONVERT I/O specifier. */ diff --git a/gcc/fortran/options.c b/gcc/fortran/options.c index 9296a0be667..a9ce56015ae 100644 --- a/gcc/fortran/options.c +++ b/gcc/fortran/options.c @@ -482,11 +482,12 @@ gfc_handle_runtime_check_option (const char *arg) { int result, pos = 0, n; static const char * const optname[] = { "all", "bounds", "array-temps", - "recursion", "do", "pointer", NULL }; + "recursion", "do", "pointer", + "mem", NULL }; static const int optmask[] = { GFC_RTCHECK_ALL, GFC_RTCHECK_BOUNDS, GFC_RTCHECK_ARRAY_TEMPS, GFC_RTCHECK_RECURSION, GFC_RTCHECK_DO, - GFC_RTCHECK_POINTER, + GFC_RTCHECK_POINTER, GFC_RTCHECK_MEM, 0 }; while (*arg) diff --git a/gcc/fortran/trans.c b/gcc/fortran/trans.c index 535e639faad..6958f0272b5 100644 --- a/gcc/fortran/trans.c +++ b/gcc/fortran/trans.c @@ -497,13 +497,12 @@ gfc_trans_runtime_check (bool error, bool once, tree cond, stmtblock_t * pblock, /* Call malloc to allocate size bytes of memory, with special conditions: - + if size < 0, generate a runtime error, - + if size == 0, return a malloced area of size 1, + + if size <= 0, return a malloced area of size 1, + if malloc returns NULL, issue a runtime error. */ tree gfc_call_malloc (stmtblock_t * block, tree type, tree size) { - tree tmp, msg, negative, malloc_result, null_result, res; + tree tmp, msg, malloc_result, null_result, res; stmtblock_t block2; size = gfc_evaluate_now (size, block); @@ -514,18 +513,7 @@ gfc_call_malloc (stmtblock_t * block, tree type, tree size) /* Create a variable to hold the result. */ res = gfc_create_var (prvoid_type_node, NULL); - /* size < 0 ? */ - negative = fold_build2 (LT_EXPR, boolean_type_node, size, - build_int_cst (size_type_node, 0)); - msg = gfc_build_addr_expr (pchar_type_node, gfc_build_localized_cstring_const - ("Attempt to allocate a negative amount of memory.")); - tmp = fold_build3 (COND_EXPR, void_type_node, negative, - build_call_expr_loc (input_location, - gfor_fndecl_runtime_error, 1, msg), - build_empty_stmt (input_location)); - gfc_add_expr_to_block (block, tmp); - - /* Call malloc and check the result. */ + /* Call malloc. */ gfc_start_block (&block2); size = fold_build2 (MAX_EXPR, size_type_node, size, @@ -535,15 +523,21 @@ gfc_call_malloc (stmtblock_t * block, tree type, tree size) fold_convert (prvoid_type_node, build_call_expr_loc (input_location, built_in_decls[BUILT_IN_MALLOC], 1, size))); - null_result = fold_build2 (EQ_EXPR, boolean_type_node, res, - build_int_cst (pvoid_type_node, 0)); - msg = gfc_build_addr_expr (pchar_type_node, gfc_build_localized_cstring_const - ("Memory allocation failed")); - tmp = fold_build3 (COND_EXPR, void_type_node, null_result, - build_call_expr_loc (input_location, - gfor_fndecl_os_error, 1, msg), - build_empty_stmt (input_location)); - gfc_add_expr_to_block (&block2, tmp); + + /* Optionally check whether malloc was successful. */ + if (gfc_option.rtcheck & GFC_RTCHECK_MEM) + { + null_result = fold_build2 (EQ_EXPR, boolean_type_node, res, + build_int_cst (pvoid_type_node, 0)); + msg = gfc_build_addr_expr (pchar_type_node, + gfc_build_localized_cstring_const ("Memory allocation failed")); + tmp = fold_build3 (COND_EXPR, void_type_node, null_result, + build_call_expr_loc (input_location, + gfor_fndecl_os_error, 1, msg), + build_empty_stmt (input_location)); + gfc_add_expr_to_block (&block2, tmp); + } + malloc_result = gfc_finish_block (&block2); gfc_add_expr_to_block (block, malloc_result); @@ -553,6 +547,7 @@ gfc_call_malloc (stmtblock_t * block, tree type, tree size) return res; } + /* Allocate memory, using an optional status argument. This function follows the following pseudo-code: -- 2.11.0