https://gcc.gnu.org/g:ea991f752fc2a65a887c64190d8cad415edac8c9

commit r17-2596-gea991f752fc2a65a887c64190d8cad415edac8c9
Author: Thomas Koenig <[email protected]>
Date:   Tue Jul 21 19:04:48 2026 +0200

    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:
---
 gcc/fortran/resolve.cc                             | 15 +++++++++++++
 .../gfortran.dg/warn_undefined_vars_8.f90          | 17 +++++++++++++++
 .../gfortran.dg/warn_undefined_vars_9.f90          | 18 ++++++++++++++++
 .../gfortran.dg/warn_unused_but_set_variable_5.f90 | 25 ++++++++++++++++++++++
 4 files changed, 75 insertions(+)

diff --git a/gcc/fortran/resolve.cc b/gcc/fortran/resolve.cc
index 6dc1b8e315d5..5f3edb37aa4b 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 000000000000..2783745a8baf
--- /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 000000000000..59715c2e11bf
--- /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 000000000000..00ff87365c4f
--- /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