Hello world, the attached patch fixes an ICE regresseion where undo state was not handled properly when generating formal from actual arguments, which occurred under certain conditions with the newly introduced -Wexternal-argument-mismatch option.
The fix is simple: When we are generating these symbols, we no longer need to undo anything, so we can just remove them. I had considered adding an extra optional argument, but decided against it on code clarity grounds. While looking at the code, I also saw that a member of gfc_symbol introduced with my patch should be a bitfield of width 1. OK for trunk? Best regards Thomas gcc/fortran/ChangeLog: PR fortran/119157 * gfortran.h (gfc_symbol): Make ext_dummy_arglist_mismatch a one-bit bitfield (gfc_pop_undo_symbol): Declare prototype. * symbol.cc (gfc_pop_undo_symbol): New function. * interface.cc (gfc_get_formal_from_actual_arglist): Call it for artificially introduced formal variables. gcc/testsuite/ChangeLog: PR fortran/119157 * gfortran.dg/interface_57.f90: New test.
diff --git a/gcc/fortran/gfortran.h b/gcc/fortran/gfortran.h index 927f22cffd1..f81be1d984c 100644 --- a/gcc/fortran/gfortran.h +++ b/gcc/fortran/gfortran.h @@ -2026,7 +2026,7 @@ typedef struct gfc_symbol /* Set if an external dummy argument is called with different argument lists. This is legal in Fortran, but can cause problems with autogenerated C prototypes for C23. */ - unsigned ext_dummy_arglist_mismatch; + unsigned ext_dummy_arglist_mismatch:1; /* Reference counter, used for memory management. @@ -3736,6 +3736,7 @@ void gfc_traverse_user_op (gfc_namespace *, void (*)(gfc_user_op *)); void gfc_save_all (gfc_namespace *); void gfc_enforce_clean_symbol_state (void); +void gfc_pop_undo_symbol (void); gfc_gsymbol *gfc_get_gsymbol (const char *, bool bind_c); gfc_gsymbol *gfc_find_gsymbol (gfc_gsymbol *, const char *); diff --git a/gcc/fortran/interface.cc b/gcc/fortran/interface.cc index edec907d33a..e3bc22f25e5 100644 --- a/gcc/fortran/interface.cc +++ b/gcc/fortran/interface.cc @@ -5836,6 +5836,8 @@ gfc_get_formal_from_actual_arglist (gfc_symbol *sym, { snprintf (name, GFC_MAX_SYMBOL_LEN, "_formal_%d", var_num ++); gfc_get_symbol (name, gfc_current_ns, &s); + /* We do not need this in an undo table. */ + gfc_pop_undo_symbol(); if (a->expr->ts.type == BT_PROCEDURE) { gfc_symbol *asym = a->expr->symtree->n.sym; diff --git a/gcc/fortran/symbol.cc b/gcc/fortran/symbol.cc index c6894810bce..3e00a660b6e 100644 --- a/gcc/fortran/symbol.cc +++ b/gcc/fortran/symbol.cc @@ -3898,6 +3898,11 @@ enforce_single_undo_checkpoint (void) gcc_checking_assert (single_undo_checkpoint_p ()); } +void +gfc_pop_undo_symbol () +{ + latest_undo_chgset->syms.pop(); +} /* Undoes all the changes made to symbols in the current statement. */ diff --git a/gcc/testsuite/gfortran.dg/interface_57.f90 b/gcc/testsuite/gfortran.dg/interface_57.f90 new file mode 100644 index 00000000000..8c99864c0fb --- /dev/null +++ b/gcc/testsuite/gfortran.dg/interface_57.f90 @@ -0,0 +1,14 @@ +! { dg-do compile } +! { dg-options "-Wexternal-argument-mismatch" } +! PR 119157 - this used to ICE because undo state was not +! correctly handled. + +MODULE lmdif_module + implicit none + CONTAINS + SUBROUTINE lmdif (fcn, m) + EXTERNAL fcn + integer m + call fcn (m) + END SUBROUTINE lmdif +END MODULE