From f657024b85d19eefb046c487a6f7e48bd4905dc9 Mon Sep 17 00:00:00 2001 From: Tobias Burnus Date: Mon, 20 Aug 2012 07:47:46 +0200 Subject: [PATCH] re PR fortran/54301 (Add optional warning if pointer assigning a local variable to a nonlocal pointer) 2012-08-20 Tobias Burnus PR fortran/54301 * expr.c (gfc_check_pointer_assign): Warn when the pointer might outlive its target. * gfortran.h (struct gfc_option_t): Add warn_target_lifetime. * options.c (gfc_init_options, set_wall, gfc_handle_option): handle it. * invoke.texi (-Wtarget-lifetime): Document it. (-Wall): Implied it. * lang.opt (-Wtarget-lifetime): New flag. 2012-08-20 Tobias Burnus PR fortran/54301 * gfortran.dg/warn_target_lifetime_1.f90: New. From-SVN: r190522 --- gcc/fortran/ChangeLog | 12 +++++ gcc/fortran/expr.c | 32 +++++++++++++ gcc/fortran/gfortran.h | 1 + gcc/fortran/invoke.texi | 11 +++-- gcc/fortran/lang.opt | 4 ++ gcc/fortran/options.c | 6 +++ gcc/testsuite/ChangeLog | 5 ++ .../gfortran.dg/warn_target_lifetime_1.f90 | 47 +++++++++++++++++++ 8 files changed, 115 insertions(+), 3 deletions(-) create mode 100644 gcc/testsuite/gfortran.dg/warn_target_lifetime_1.f90 diff --git a/gcc/fortran/ChangeLog b/gcc/fortran/ChangeLog index e91f947cd6f..de255eaf79f 100644 --- a/gcc/fortran/ChangeLog +++ b/gcc/fortran/ChangeLog @@ -1,3 +1,15 @@ +2012-08-20 Tobias Burnus + + PR fortran/54301 + * expr.c (gfc_check_pointer_assign): Warn when the pointer + might outlive its target. + * gfortran.h (struct gfc_option_t): Add warn_target_lifetime. + * options.c (gfc_init_options, set_wall, gfc_handle_option): + handle it. + * invoke.texi (-Wtarget-lifetime): Document it. + (-Wall): Implied it. + * lang.opt (-Wtarget-lifetime): New flag. + 2012-08-19 Thomas König PR fortran/54298 diff --git a/gcc/fortran/expr.c b/gcc/fortran/expr.c index 7d745285c01..6f1283d152e 100644 --- a/gcc/fortran/expr.c +++ b/gcc/fortran/expr.c @@ -3659,6 +3659,38 @@ gfc_check_pointer_assign (gfc_expr *lvalue, gfc_expr *rvalue) } } + /* Warn if it is the LHS pointer may lives longer than the RHS target. */ + if (gfc_option.warn_target_lifetime + && rvalue->expr_type == EXPR_VARIABLE + && !rvalue->symtree->n.sym->attr.save + && !attr.pointer && !rvalue->symtree->n.sym->attr.host_assoc + && !rvalue->symtree->n.sym->attr.in_common + && !rvalue->symtree->n.sym->attr.use_assoc + && !rvalue->symtree->n.sym->attr.dummy) + { + bool warn; + gfc_namespace *ns; + + warn = lvalue->symtree->n.sym->attr.dummy + || lvalue->symtree->n.sym->attr.result + || lvalue->symtree->n.sym->attr.host_assoc + || lvalue->symtree->n.sym->attr.use_assoc + || lvalue->symtree->n.sym->attr.in_common; + + if (rvalue->symtree->n.sym->ns->proc_name + && rvalue->symtree->n.sym->ns->proc_name->attr.flavor != FL_PROCEDURE + && rvalue->symtree->n.sym->ns->proc_name->attr.flavor != FL_PROGRAM) + for (ns = rvalue->symtree->n.sym->ns; + ns->proc_name && ns->proc_name->attr.flavor != FL_PROCEDURE; + ns = ns->parent) + if (ns->parent == lvalue->symtree->n.sym->ns) + warn = true; + + if (warn) + gfc_warning ("Pointer at %L in pointer assignment might outlive the " + "pointer target", &lvalue->where); + } + return SUCCESS; } diff --git a/gcc/fortran/gfortran.h b/gcc/fortran/gfortran.h index c005151d0dc..4c8a856e210 100644 --- a/gcc/fortran/gfortran.h +++ b/gcc/fortran/gfortran.h @@ -2226,6 +2226,7 @@ typedef struct int warn_realloc_lhs; int warn_realloc_lhs_all; int warn_compare_reals; + int warn_target_lifetime; int max_errors; int flag_all_intrinsics; diff --git a/gcc/fortran/invoke.texi b/gcc/fortran/invoke.texi index d962ca04da0..dfd4ca7fad0 100644 --- a/gcc/fortran/invoke.texi +++ b/gcc/fortran/invoke.texi @@ -147,7 +147,7 @@ and warnings}. -Wimplicit-procedure -Wintrinsic-shadow -Wintrinsics-std @gol -Wline-truncation -Wno-align-commons -Wno-tabs -Wreal-q-constant @gol -Wsurprising -Wunderflow -Wunused-parameter -Wrealloc-lhs Wrealloc-lhs-all @gol --fmax-errors=@var{n} -fsyntax-only -pedantic -pedantic-errors +-Wtarget-lifetime -fmax-errors=@var{n} -fsyntax-only -pedantic -pedantic-errors } @item Debugging Options @@ -729,8 +729,8 @@ we recommend avoiding and that we believe are easy to avoid. This currently includes @option{-Waliasing}, @option{-Wampersand}, @option{-Wconversion}, @option{-Wcompare-reals}, @option{-Wsurprising}, @option{-Wintrinsics-std}, @option{-Wno-tabs}, @option{-Wintrinsic-shadow}, -@option{-Wline-truncation}, @option{-Wreal-q-constant} and -@option{-Wunused}. +@option{-Wline-truncation}, @option{-Wtarget-lifetime}, +@option{-Wreal-q-constant} and @option{-Wunused}. @item -Waliasing @opindex @code{Waliasing} @@ -941,6 +941,11 @@ allocatable variable; this includes scalars and derived types. Warn when comparing real or complex types for equality or inequality. Enabled by @option{-Wall}. +@item -Wtarget-lifetime +@opindex @code{Wtargt-lifetime} +Warn if the pointer in a pointer assignment might be longer than the its +target. This option is implied by @option{-Wall}. + @item -Werror @opindex @code{Werror} @cindex warnings, to errors diff --git a/gcc/fortran/lang.opt b/gcc/fortran/lang.opt index e0c7cf77ea4..b38b1e8bea1 100644 --- a/gcc/fortran/lang.opt +++ b/gcc/fortran/lang.opt @@ -262,6 +262,10 @@ Wrealloc-lhs-all Fortran Warning Warn when a left-hand-side variable is reallocated +Wtarget-lifetime +Fortran Warning +Warn if the pointer in a pointer assignment might outlive its target + Wreturn-type Fortran Warning ; Documented in C diff --git a/gcc/fortran/options.c b/gcc/fortran/options.c index 3e4444dfcf1..cbec705b195 100644 --- a/gcc/fortran/options.c +++ b/gcc/fortran/options.c @@ -114,6 +114,7 @@ gfc_init_options (unsigned int decoded_options_count, gfc_option.warn_realloc_lhs = 0; gfc_option.warn_realloc_lhs_all = 0; gfc_option.warn_compare_reals = 0; + gfc_option.warn_target_lifetime = 0; gfc_option.max_errors = 25; gfc_option.flag_all_intrinsics = 0; @@ -475,6 +476,7 @@ set_Wall (int setting) gfc_option.warn_real_q_constant = setting; gfc_option.warn_unused_dummy_argument = setting; gfc_option.warn_compare_reals = setting; + gfc_option.warn_target_lifetime = setting; warn_return_type = setting; warn_switch = setting; @@ -688,6 +690,10 @@ gfc_handle_option (size_t scode, const char *arg, int value, gfc_option.warn_tabs = value; break; + case OPT_Wtarget_lifetime: + gfc_option.warn_target_lifetime = value; + break; + case OPT_Wunderflow: gfc_option.warn_underflow = value; break; diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 1e294339f2a..c115e553b9c 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2012-08-20 Tobias Burnus + + PR fortran/54301 + * gfortran.dg/warn_target_lifetime_1.f90: New. + 2012-08-19 Thomas König PR fortran/54298 diff --git a/gcc/testsuite/gfortran.dg/warn_target_lifetime_1.f90 b/gcc/testsuite/gfortran.dg/warn_target_lifetime_1.f90 new file mode 100644 index 00000000000..fafa0f123bd --- /dev/null +++ b/gcc/testsuite/gfortran.dg/warn_target_lifetime_1.f90 @@ -0,0 +1,47 @@ +! { dg-do compile } +! { dg-options "-Wtarget-lifetime" } +! +! PR fortran/54301 +! +function f () result (ptr) + integer, pointer :: ptr(:) + integer, allocatable, target :: a(:) + allocate(a(5)) + + ptr => a ! { dg-warning "Pointer at .1. in pointer assignment might outlive the pointer target" } + a = [1,2,3,4,5] +end function + + +subroutine foo() + integer, pointer :: ptr(:) + call bar () +contains + subroutine bar () + integer, target :: tgt(5) + ptr => tgt ! { dg-warning "Pointer at .1. in pointer assignment might outlive the pointer target" } + end subroutine bar +end subroutine foo + +function foo3(tgt) + integer, target :: tgt + integer, pointer :: foo3 + foo3 => tgt +end function + +subroutine sub() + implicit none + integer, pointer :: ptr + integer, target :: tgt + ptr => tgt + + block + integer, pointer :: p2 + integer, target :: tgt2 + p2 => tgt2 + p2 => tgt + ptr => p2 + ptr => tgt + ptr => tgt2 ! { dg-warning "Pointer at .1. in pointer assignment might outlive the pointer target" } + end block +end subroutine sub