Hi Jerry, You didn't see either ChangeLog or patch because they weren't attached. Remedied for everyone else.
Cheers Paul On Fri, 21 Nov 2025 at 20:07, Jerry D <[email protected]> wrote: > On 11/21/25 8:45 AM, Paul Richard Thomas wrote: > > Hi All, > > > > I have to confess that I had never spotted the two PDT examples in the > > F2018 standard. To my horror, they both fail. > > > > The second example involves finalizers of PDTs and is already caught by > > 104650. I am onto that one as well :-) > > > > A PDT typespec in a function declaration such as; > > > > CONTAINS > > TYPE(t(single)) FUNCTION real_to_t1(x) > > REAL(single) x > > real_to_t1%value = x > > END FUNCTION > > > > causes gfc_use_derived to emit, "Derived type ‘pdtt_4’ at (1) is being > > used before it is defined", whereas this; > > > > CONTAINS > > FUNCTION real_to_t1(x) > > TYPE(t(single)) real_to_t1 > > REAL(single) x > > real_to_t1%value = x > > END FUNCTION > > > > compiled and ran successfully. The attached patch fixes this problem and > > is explained by the ChangeLog and the comment in the patch. > > > > Regtest OK on FC43/x86_64. OK for mainline? > > > > Paul > > I did not see the patch attached, however I tested it off of bugzilla. > > OK from my point of view. > > Jerry >
Change.Logs
Description: Binary data
diff --git a/gcc/fortran/decl.cc b/gcc/fortran/decl.cc
index 03134f39a40..1346f329e61 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 00000000000..6f66aa8c8c6
--- /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
