Hello world,

what it says in the ChangeLog entry. This fixes a few false positives.

Regression-tested. OK for trunk?

Best regards

        Thomas

Mark variables in references for variable definition context as used.

Code like "a(i) = 42" would not mark i as used, leading to false
positives for warnings with -Wunused-but-set-variable.  This is fixed
in the attached patch.  It also removes some default arguments to
make sure that the caller side provides correct information.

gcc/fortran/ChangeLog:

        PR fortran/30438
        * gfortran.h (gfc_value_set_at): Remove default argument.
        (gfc_expr_set_at): Add prototype.
        * interface.cc (gfc_compare_actual_formal): Use gfc_expr_set_at.
        * intrinsic.cc (mark_args_as_used): Likewise.
        * io.cc (resolve_tag): Likewise.
        (gfc_resolve_dt): Likewise.
        (gfc_resolve_inquire): Likewise.
        * resolve.cc (resolve_transfer): Likewise.
        (mark_lhs_assignments_set): Likewise.
        * symbol.cc (gfc_lvalue_allocated_at): Add comment, fix formatting.
        (gfc_expr_set_at): New fuction.

gcc/testsuite/ChangeLog:

        PR fortran/30438
        * gfortran.dg/warn_unused_but_set_variable_2.f90: New test.
diff --git a/gcc/fortran/gfortran.h b/gcc/fortran/gfortran.h
index 01c88c78a06..f212de6315a 100644
--- a/gcc/fortran/gfortran.h
+++ b/gcc/fortran/gfortran.h
@@ -3992,9 +3992,8 @@ void gfc_warn_intrinsic_shadow (const gfc_symbol*, bool, bool);
 bool gfc_check_intrinsic_standard (const gfc_intrinsic_sym*, const char**,
 				      bool, locus);
 
-bool gfc_value_set_at (gfc_symbol *, locus *loc = NULL,
-		       enum value_set = VALUE_VARDEF);
-
+bool gfc_value_set_at (gfc_symbol *, locus *loc,
+		       enum value_set);
 bool gfc_lvalue_allocated_at (gfc_symbol *, locus *);
 void gfc_mark_lhs_as_used (gfc_expr *, locus *);
 
@@ -4002,6 +4001,8 @@ void gfc_value_used_expr (gfc_expr *, enum value_used);
 void gfc_value_set_and_used (gfc_expr *, locus *loc,
 			     enum value_set, enum value_used);
 void gfc_used_in_allocate_expr (gfc_expr *, locus *loc);
+void gfc_expr_set_at (gfc_expr *, locus *loc, enum value_set);
+
 
 /* match.cc -- FIXME */
 void gfc_free_iterator (gfc_iterator *, int);
diff --git a/gcc/fortran/interface.cc b/gcc/fortran/interface.cc
index ed898506d0e..ece708efe86 100644
--- a/gcc/fortran/interface.cc
+++ b/gcc/fortran/interface.cc
@@ -4241,7 +4241,7 @@ gfc_compare_actual_formal (gfc_actual_arglist **ap, gfc_formal_arglist *formal,
 	      case INTENT_OUT:
 		{
 		  gfc_symbol *s = e->symtree->n.sym;
-		  gfc_value_set_at (s, &e->where, VALUE_INTENT_OUT);
+		  gfc_expr_set_at (e, &e->where, VALUE_INTENT_OUT);
 
 		  /* INTENT(OUT) allocates variables as far as we know.  */
 		  if (s->attr.allocatable)
diff --git a/gcc/fortran/intrinsic.cc b/gcc/fortran/intrinsic.cc
index 969f5368f3a..87a223ceb95 100644
--- a/gcc/fortran/intrinsic.cc
+++ b/gcc/fortran/intrinsic.cc
@@ -4991,7 +4991,7 @@ mark_args_as_used (gfc_intrinsic_arg *f, gfc_actual_arglist *a)
 	      if (a->expr->expr_type == EXPR_VARIABLE)
 		{
 		  gfc_symbol *s = a->expr->symtree->n.sym;
-		  gfc_value_set_at (s, &a->expr->where, VALUE_INTENT_OUT);
+		  gfc_expr_set_at (a->expr, &a->expr->where, VALUE_INTENT_OUT);
 		  if (s->attr.allocatable)
 		    s->attr.allocated = 1;
 		}
diff --git a/gcc/fortran/io.cc b/gcc/fortran/io.cc
index 85ff06fbda0..4720ea9a1f2 100644
--- a/gcc/fortran/io.cc
+++ b/gcc/fortran/io.cc
@@ -1922,7 +1922,7 @@ resolve_tag (const io_tag *tag, gfc_expr *e)
       if (!gfc_check_vardef_context (e, false, false, false, context))
 	return false;
 
-      gfc_value_set_at (e->symtree->n.sym, &e->where, VALUE_VARDEF);
+      gfc_expr_set_at (e, &e->where, VALUE_VARDEF);
     }
   else
     gfc_value_used_expr (e, VALUE_USED);
@@ -3410,7 +3410,7 @@ gfc_resolve_dt (gfc_code *dt_code, gfc_dt *dt, locus *loc)
 					_("internal unit in WRITE")))
 	    return false;
 
-	  gfc_value_set_at (e->symtree->n.sym, &e->where);
+	  gfc_expr_set_at (e, &e->where, VALUE_VARDEF);
 	}
     }
 
@@ -3455,7 +3455,7 @@ gfc_resolve_dt (gfc_code *dt_code, gfc_dt *dt, locus *loc)
 			     dt->namelist->name, loc, n->sym->name);
 		  return false;
 		}
-	      gfc_value_set_at (n->sym, NULL);
+	      gfc_value_set_at (n->sym, NULL, VALUE_VARDEF);
 	    }
 
 	  t = dtio_procs_present (n->sym, k);
@@ -4793,7 +4793,7 @@ gfc_resolve_inquire (gfc_inquire *inquire)
       if (gfc_check_vardef_context ((expr), false, false, false, \
 				    context) == false) \
 	return false; \
-      gfc_value_set_at (expr->symtree->n.sym, &expr->where); \
+      gfc_expr_set_at (expr, &expr->where, VALUE_VARDEF);	\
     }
   INQUIRE_RESOLVE_TAG (&tag_iomsg, inquire->iomsg);
   INQUIRE_RESOLVE_TAG (&tag_iostat, inquire->iostat);
diff --git a/gcc/fortran/resolve.cc b/gcc/fortran/resolve.cc
index 74cafd30149..0a7f85f90a0 100644
--- a/gcc/fortran/resolve.cc
+++ b/gcc/fortran/resolve.cc
@@ -9745,7 +9745,7 @@ success:
   gfc_used_in_allocate_expr (e, &e->where);
 
   if (code->expr3)
-    gfc_value_set_at (e->symtree->n.sym, &code->expr3->where);
+    gfc_value_set_at (e->symtree->n.sym, &code->expr3->where, VALUE_VARDEF);
 
   return true;
 
@@ -11776,7 +11776,7 @@ resolve_transfer (gfc_code *code)
 				     _("item in READ")))
 	return;
 
-      gfc_value_set_at (exp->symtree->n.sym, &exp->where, VALUE_READ);
+      gfc_expr_set_at (exp, &exp->where, VALUE_READ);
     }
 
   const gfc_typespec *ts = exp->expr_type == EXPR_STRUCTURE
@@ -20562,7 +20562,7 @@ mark_lhs_assignments_set (gfc_code *code)
 
 	  gcc_fallthrough();
 	case EXEC_POINTER_ASSIGN:
-	  gfc_value_set_at (lvalue->symtree->n.sym, &rvalue->where);
+	  gfc_expr_set_at (lvalue, &rvalue->where, VALUE_VARDEF);
 	default:
 	  break;
 	}
diff --git a/gcc/fortran/symbol.cc b/gcc/fortran/symbol.cc
index c2dd42840b5..2ce7e000a05 100644
--- a/gcc/fortran/symbol.cc
+++ b/gcc/fortran/symbol.cc
@@ -5909,8 +5909,10 @@ gfc_used_in_allocate_expr (gfc_expr *expr, locus *loc)
     sym->extra_loc = *loc;
 }
 
+/* Mark a symbol to allocated.  */
 
-bool gfc_lvalue_allocated_at (gfc_symbol *sym, locus *loc)
+bool
+gfc_lvalue_allocated_at (gfc_symbol *sym, locus *loc)
 {
   if (sym->other_loc.nextc == 0)
     sym->other_loc = *loc;
@@ -5918,3 +5920,28 @@ bool gfc_lvalue_allocated_at (gfc_symbol *sym, locus *loc)
   sym->attr.allocated = 1;
   return true;
 }
+
+/* Mark the variable of an expression in a vardef context as
+   set and mark everything in the references as used.  */
+
+void
+gfc_expr_set_at (gfc_expr *expr, locus *loc, enum value_set how_set)
+{
+  enum value_used prev_used;
+  gfc_symbol *sym;
+  locus prev_loc;
+
+  if (!expr)
+    return;
+
+  if (expr->expr_type != EXPR_VARIABLE)
+    return;
+
+  sym = expr->symtree->n.sym;
+  gfc_value_set_at (sym, loc, how_set);
+  prev_used = sym->attr.value_used;
+  prev_loc = sym->other_loc;
+  gfc_value_used_expr (expr, VALUE_USED);
+  sym->other_loc = prev_loc;
+  sym->attr.value_used = prev_used;
+}
diff --git a/gcc/testsuite/gfortran.dg/warn_unused_but_set_variable_2.f90 b/gcc/testsuite/gfortran.dg/warn_unused_but_set_variable_2.f90
new file mode 100644
index 00000000000..19e008673cc
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/warn_unused_but_set_variable_2.f90
@@ -0,0 +1,16 @@
+! { dg-do compile }
+! { dg-additional-options "-Wunused-but-set-variable" }
+program main
+  integer :: i,j, k
+  real, dimension(100) :: a
+  integer, dimension(50) :: ios
+  i = 42
+  j = 42
+  read (*,*) a(i)
+  print *, a(j)
+
+  k = 42
+  read (*,*,iostat=ios(k)) a(10)
+  print *,ios(42)
+end program main
+  

Reply via email to