Hello world,

what it says in the ChangeLog.  Regression-tested. OK for trunk?

Best regards

        Thomas

Fix a few false positive warnings with unused/undefined warnings.

Trying out the new warnings on actual code found a new false positives.
The charlen of an ALLOCATE was not marked as used, the expression
in SELECT CASE was not marked as used and host-associated variables
were not exempt from testing.

All fixed with the attached patch.

gcc/fortran/ChangeLog:

        PR fortran/126333
        * resolve.cc (resolve_allocate_deallocate): Resolve charlen of ts
        and set as used if present.
        (resolve_select): Mark code->expr1 as used.
        (find_unused_vs_set): Do not complain about host-associated
        variables which are not marked private.

gcc/testsuite/ChangeLog:

        PR fortran/126333
        * gfortran.dg/warn_undefined_vars_8.f90: New test.
        * gfortran.dg/warn_undefined_vars_9.f90: New test.
        * gfortran.dg/warn_unused_but_set_variable_5.f90: New test.
diff --git a/gcc/fortran/resolve.cc b/gcc/fortran/resolve.cc
index 6dc1b8e315d..5f3edb37aa4 100644
--- a/gcc/fortran/resolve.cc
+++ b/gcc/fortran/resolve.cc
@@ -9961,6 +9961,14 @@ done_errmsg:
     {
       bool arr_alloc_wo_spec = false;
 
+      /* Resolve and mark as used the length of the type spec.  */
+      if (code->ext.alloc.ts.type == BT_CHARACTER)
+	{
+	  gfc_expr *length = code->ext.alloc.ts.u.cl->length;
+	  gfc_resolve_expr (length);
+	  gfc_value_used_expr (length, VALUE_USED);
+	}
+
       /* Resolving the expr3 in the loop over all objects to allocate would
 	 execute loop invariant code for each loop item.  Therefore do it just
 	 once here.  */
@@ -10274,6 +10282,7 @@ resolve_select (gfc_code *code, bool select_type)
 	 GOTOs as normal SELECTs from here on.  */
       code->expr1 = code->expr2;
       code->expr2 = NULL;
+      gfc_value_used_expr (code->expr1, VALUE_USED);
       return;
     }
 
@@ -10542,6 +10551,9 @@ resolve_select (gfc_code *code, bool select_type)
     gfc_warning (OPT_Wsurprising,
 		 "Logical SELECT CASE block at %L has more that two cases",
 		 &code->loc);
+
+  /* Finally, mark the expression as used.  */
+  gfc_value_used_expr (case_expr, VALUE_USED);
 }
 
 
@@ -20840,6 +20852,9 @@ find_unused_vs_set (gfc_symbol *sym)
       || attr->volatile_ || attr->asynchronous || !attr->referenced)
     return;
 
+  if (attr->host_assoc && attr->access != ACCESS_PRIVATE)
+    return;
+
   /* There is no allocation in sight, but the variable is used anyway.  This
      might be hidden behind PRESENT, but issue a warning nonetheless.  If
      people complain, we might want to make this to an extra option to be
diff --git a/gcc/testsuite/gfortran.dg/warn_undefined_vars_8.f90 b/gcc/testsuite/gfortran.dg/warn_undefined_vars_8.f90
new file mode 100644
index 00000000000..2783745a8ba
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/warn_undefined_vars_8.f90
@@ -0,0 +1,17 @@
+! { dg-do compile }
+! { dg-additional-options "-Wundefined-vars" }
+! A variable referenced in a charlen was not tracked for warnings.
+
+program memain
+  implicit none
+  character(len=:), allocatable :: c, d
+  integer :: n, m
+  n = 42
+  allocate (character(len=n) :: c)
+  read (*,*) c
+  print *,c
+  ! m = 21
+  allocate (character(len=m) :: d) ! { dg-warning "Undefined variable" }
+  read (*,*) d
+  print *,d
+end program memain
diff --git a/gcc/testsuite/gfortran.dg/warn_undefined_vars_9.f90 b/gcc/testsuite/gfortran.dg/warn_undefined_vars_9.f90
new file mode 100644
index 00000000000..59715c2e11b
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/warn_undefined_vars_9.f90
@@ -0,0 +1,18 @@
+! { dg-do compile }
+! { dg-additional-options "-Wundefined-vars" }
+! In the code below, a can be allocated by calling bar and
+! c from the outside.
+module x
+  implicit none
+  integer, allocatable, private, dimension(:) :: a, b
+  integer, allocatable, public, dimension(:) :: c
+contains
+  subroutine foo
+    print *,a
+    print *,b ! { dg-warning "Unallocated variable" }
+    print *,c
+  end subroutine foo
+  subroutine bar
+    a = [1,2,3]
+  end subroutine bar
+end module x
diff --git a/gcc/testsuite/gfortran.dg/warn_unused_but_set_variable_5.f90 b/gcc/testsuite/gfortran.dg/warn_unused_but_set_variable_5.f90
new file mode 100644
index 00000000000..00ff87365c4
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/warn_unused_but_set_variable_5.f90
@@ -0,0 +1,25 @@
+! { dg-do compile }
+! { dg-additional-options "-Wunused-but-set-variable" }
+
+module x
+  implicit none
+contains
+  function asdf() result(res)
+    character(len=1) :: res
+    integer :: i
+    read (*,*) i
+    select case(i)
+    case(1)
+       res = 'a'
+    case(2)
+       res = 's'
+    case(3)
+       res = 'd'
+    case(4)
+       res = 'f'
+    case default
+       res = ' '
+    end select
+  end function asdf
+end module x
+  

Reply via email to