https://gcc.gnu.org/g:77f4a4f4d17726492960a582e57c781dc89f15bb
commit r16-5542-g77f4a4f4d17726492960a582e57c781dc89f15bb Author: Paul Thomas <[email protected]> Date: Mon Nov 24 11:30:19 2025 +0000 Fortran: Failure with 1st PDT example in F2018 standard [PR122766] 2025-11-24 Paul Thomas <[email protected]> gcc/fortran PR fortran/122766 * decl.cc (gfc_match_decl_type_spec): A pdt_type found while parsing a contains section can only arise from the typespec of a function declaration. This can be retained in the typespec. Once we are parsing the function, the first reference to this derived type will find that it has no symtree. Provide it with one so that gfc_use_derived does not complain and, again,retain it in the typespec. gcc/testsuite PR fortran/122766 * gfortran.dg/pdt_69.f03: New test. Diff: --- gcc/fortran/decl.cc | 27 ++++++++++++++++- gcc/testsuite/gfortran.dg/pdt_69.f03 | 58 ++++++++++++++++++++++++++++++++++++ 2 files changed, 84 insertions(+), 1 deletion(-) diff --git a/gcc/fortran/decl.cc b/gcc/fortran/decl.cc index 03134f39a404..1346f329e612 100644 --- a/gcc/fortran/decl.cc +++ b/gcc/fortran/decl.cc @@ -4824,6 +4824,31 @@ gfc_match_decl_type_spec (gfc_typespec *ts, int implicit_flag) return m; } + /* This picks up function declarations with a PDT typespec. Since a + pdt_type has been generated, there is no more to do. Within the + function body, this type must be used for the typespec so that + the "being used before it is defined warning" does not arise. */ + if (ts->type == BT_DERIVED + && sym && sym->attr.pdt_type + && (gfc_current_state () == COMP_CONTAINS + || (gfc_current_state () == COMP_FUNCTION + && gfc_current_block ()->ts.type == BT_DERIVED + && gfc_current_block ()->ts.u.derived == sym + && !gfc_find_symtree (gfc_current_ns->sym_root, + sym->name)))) + { + if (gfc_current_state () == COMP_FUNCTION) + { + gfc_symtree *pdt_st; + pdt_st = gfc_new_symtree (&gfc_current_ns->sym_root, + sym->name); + pdt_st->n.sym = sym; + sym->refs++; + } + ts->u.derived = sym; + return MATCH_YES; + } + /* Defer association of the derived type until the end of the specification block. However, if the derived type can be found, add it to the typespec. */ @@ -4860,7 +4885,7 @@ gfc_match_decl_type_spec (gfc_typespec *ts, int implicit_flag) dt_sym = gfc_find_dt_in_generic (sym); /* Host associated PDTs can get confused with their constructors - because they ar instantiated in the template's namespace. */ + because they are instantiated in the template's namespace. */ if (!dt_sym) { if (gfc_find_symbol (dt_name, NULL, 1, &dt_sym)) diff --git a/gcc/testsuite/gfortran.dg/pdt_69.f03 b/gcc/testsuite/gfortran.dg/pdt_69.f03 new file mode 100644 index 000000000000..62173373b9eb --- /dev/null +++ b/gcc/testsuite/gfortran.dg/pdt_69.f03 @@ -0,0 +1,58 @@ +! { dg-do compile } +! +! Test the fix for PR12276. +! Exmple from F2018: C.2.5 Structure constructors and generic names +! Failed in each of the functions with, for example: +! "Derived type ‘pdtt_4’ at (1) is being used before it is defined" +! For each of the functions, if the function type was declared within +! the function, all was well. +! +MODULE m + TYPE t(kind) + INTEGER, KIND :: kind + COMPLEX(kind) value + END TYPE + INTEGER,PARAMETER :: single = KIND(0.0), double = KIND(0d0) + + INTERFACE t + MODULE PROCEDURE real_to_t1, dble_to_t2, int_to_t1, int_to_t2 + END INTERFACE + + CONTAINS + TYPE(t(single)) FUNCTION real_to_t1(x) + REAL(single) x + real_to_t1%value = x + END FUNCTION + + TYPE(t(double)) FUNCTION dble_to_t2(x) + REAL(double) x + dble_to_t2%value = x + END FUNCTION + TYPE(t(single)) FUNCTION int_to_t1(x,mold) + INTEGER x + TYPE(t(single)) mold + int_to_t1%value = x + END FUNCTION + TYPE(t(double)) FUNCTION int_to_t2(x,mold) + INTEGER x + TYPE(t(double)) mold + int_to_t2%value = x + END FUNCTION + + END + + PROGRAM example + USE m + TYPE(t(single)) x + TYPE(t(double)) y + x = t(1.5) ! References real_to_t1 + print *, x%value + x = t(17,mold=x) ! References int_to_t1 + print *, x%value + y = t(1.5d0) ! References dble_to_t2 + print *, y%value + y = t(42,mold=y) ! References int_to_t2 + print *, y%value + y = t(kind(0d0)) ((0,1)) ! Uses the structure constructor for type t + print *, y%value + END
