https://gcc.gnu.org/bugzilla/show_bug.cgi?id=30438
--- Comment #14 from GCC Commits <cvs-commit at gcc dot gnu.org> --- The trunk branch has been updated by Thomas Koenig <[email protected]>: https://gcc.gnu.org/g:9d868e49122b4ce45cffa4d3f47f6ef371e80a24 commit r17-1502-g9d868e49122b4ce45cffa4d3f47f6ef371e80a24 Author: Thomas Koenig <[email protected]> Date: Tue Jun 9 07:09:23 2026 +0200 Implement warnings based on variable definition and use. This patch grew from trying to implement PR 30438 into something bigger. This now warns about variables which were never defined, but are used via a new option -Wundefined-vars and implements -Wunused-but-set-variable for Fortran. It works by keeping tabls of several things in the attributes of a variable: If and how it has been set (via value_set), used (via value_used), if it has been allocated (via allocated) and if a warning has already been emitted for the symbol. This looks at statements in a namespace only; control flow is *not* considered. In every corner of the compiler that I could find where values are set or used, flags are set accodingly. Updates are done if the new use is considered to be more "important" than the old one. The location of use or definition is also recorded, as is the place where a variable may be allocated. After all the flags have been correctly set (one at least hopes) gfc_resolve then calls warn_unused_vs_set, which then iterates over the symbols, calling find_unused_vs_set where all warnings are emitted. I tried to be conservative here to avoid false positives, so a whole lot of conditions are excluded (see the top of the function). I thought a bit on where to put -Wunused-read and -Wunused-intent-out. While reading in a value and then not using it, or getting it from an INTENT(OUT) argument may be dubious, people could use it for skipping over unneeded data or because an API requires it. Hence, I feld that -Wall would be too harsh, but I am open to discussion here. The warn_undefined_vars_* tests are split because the testsuite would not find warnings in certain lines even though they were issued and I tried out ! { dg-warning ".+" } . I suspect some strangeness/bug in gfortran.dg, but did not investigate further. gcc/fortran/ChangeLog: PR fortran/30438 PR fortran/28004 * dump-parse-tree.cc (gfc_debug_code_node): New function. (show_attr): Add select_rank_temporary. Fix typo. Add referenced, value_set, allocated and value_used. * gfortran.h (enum value_set): New enum. (enum value_used): New enum. (gfc_symbol): Add value_set, value_used, allocated and warning_emitted attributes. Rename formal_at to other_loc. Add extra_loc. (gfc_value_set_at): Add prototype. (gfc_lvalue_allocated_at): Likewise. (gfc_mark_lhs_as_used): Likewise. (gfc_value_used_expr): Likewise. (gfc_value_set_and_used): Likewise. (gfc_used_in_allocate_expr): Likewise. * interface.cc (gfc_compare_actual_formal): Mark actual arguments according to INTENT and VALUE on formal arguments. (gfc_procedure_use): Add VALUE_ARG/VALUE_MAYBE_USED for implicit arguments. * intrinsic.cc (mark_args_as_used): New function. (init_arglist): Adjust comment. (gfc_intrinsic_sub_interface): Use mark_args_as_used. * invoke.texi: Document -Wundefined-vars, -Wunused-intent-out and -Wunused-read. * io.cc (resolve_tag_format): Mark expressions as used. (resolve_tag): Mark as used or set, depending on tag. (gfc_resolve_dt): Mark internal unit as set. (gfc_resolve_inquire): Mark value as set for INQUIRE_RESOLVE_TAG macro. * lang.opt: Add -Wundefined-vars, -Wunused-intent-out and -Wunused-read. * lang.opt.urls: Regenerated. * resolve.cc (resolve_function): Replace formal_at by other_loc. (resolve_call): Likewise. (gfc_resolve_iterator): Mark iterator variable as set and used and other expressions as used. (resolve_forall_iterators): Likewise. (resolve_allocate_expr): On success, call gfc_used_in_allocate_expr and mark value as set if source is present. (resolve_transfer): Mark set/read according to context. (gfc_resolve_blocks): Mark expr1 and expr2 as used. (mark_lhs_assignments_set): Prototype / new function. (gfc_resolve_code): Mark expr2, expr3 and expr4 as used. (var_value_is_used): New function. (var_value_is_set): New function. (find_unused_vs_set): New function. (warn_unused_vs_set): New function. (gfc_resolve): Call warn_unused_vs_set. * symbol.cc (gfc_value_set_at): New function. (mark_vars_as_used): New function. (gfc_value_used_expr): New function. (gfc_value_set_and_used): New function. (gfc_used_in_allocate_expr): new function. (gfc_lvalue_allocated_at): New function. * trans-decl.cc (gfc_finish_var_decl): If we already emitted a warning, suppress further middle-end warning o that variable. libgfortran/ChangeLog: PR fortran/30438 PR fortran/28004 * mk-kinds-h.sh: Add print statement so test will compile with -Wall -Werror. * mk-sik-inc.sh: Likewise. * mk-srk-inc.sh: Likewise. libgomp/ChangeLog: PR fortran/30438 PR fortran/28004 * testsuite/libgomp.fortran/alloc-1.F90: Shut up -Wunused-but-set-variable. * testsuite/libgomp.fortran/alloc-12.f90: Likewise. gcc/testsuite/ChangeLog: PR fortran/30438 PR fortran/28004 * gfortran.dg/allocatable_length.f90: Add -Wno-undefined-vars. * gfortran.dg/allocatable_scalar_6.f90: Likewise. * gfortran.dg/allocatable_uninitialized_1.f90: Add -Wno-unused-but-set-variable -Wno-undefined-vars. * gfortran.dg/assignment_4.f90: Add -Wno-undefined-vars. * gfortran.dg/attr_deprecated-2.f90: Likewise. * gfortran.dg/c_by_val_5.f90: Add -Wno-unused-but-set-variable. * gfortran.dg/char_component_initializer_2.f90: Shut up warning. * gfortran.dg/char_length_1.f90: Add statement to shut up warning. * gfortran.dg/constructor_9.f90: Add -Wno-unused-but-set-variable. * gfortran.dg/gamma_2.f90: Add statement to shut up warning. * gfortran.dg/gomp/allocate-10.f90: Add -Wno-unused-but-set-variable. * gfortran.dg/io_constraints_8.f90: Likewise. * gfortran.dg/label_5.f90: Likewise. * gfortran.dg/len_trim.f90: Likewise. * gfortran.dg/linefile.f90: Likewise. * gfortran.dg/pointer_check_13.f90: Add dg-warning. * gfortran.dg/pr102366.f90: Add -Wno-unused-but-set-variable. * gfortran.dg/pr103475.f90: Likewise. * gfortran.dg/pr91497.f90: Likewise. * gfortran.dg/pr91497_2.f90: Likewise. * gfortran.dg/pr96312.f90: Likewise. * gfortran.dg/pr98411.f90: Likewise. * gfortran.dg/transfer_check_4.f90: Likewise. * gfortran.dg/warnings_are_errors_1.f90: Add print statement. * gfortran.dg/warn_undefined_vars_1.f90: New test. * gfortran.dg/warn_undefined_vars_2.f90: New test. * gfortran.dg/warn_undefined_vars_3.f90: New test. * gfortran.dg/warn_undefined_vars_4.f90: New test. * gfortran.dg/warn_unused_intent_out_1.f90: New test. * gfortran.dg/warn_unused_read_1.f90: New test.
