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
+