Fix regression with -Wexternal-argument-mismatch.

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.

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.
This commit is contained in:
Thomas Koenig 2025-03-08 16:13:41 +01:00
parent 613f8ddbe3
commit 90d9cdfa82
4 changed files with 23 additions and 1 deletions

View file

@ -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 *);

View file

@ -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;

View file

@ -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. */

View file

@ -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