Skip to content

Commit 071942e

Browse files
author
Paul Thomas
committed
Fortran: Fix PDT constructors in associate [PR122501, PR122524]
2025-11-05 Paul Thomas <pault@gcc.gnu.org> gcc/fortran PR fortran/122501 PR fortran/122524 * primary.cc (gfc_convert_to_structure_constructor): Correct whitespace issue. (gfc_match_rvalue): Remove the attempt to match specific procs before filling out PDT constructor. Instead, defer this until resolution with the condition that there not be a following arglist and more than one procedure in the generic interface. gcc/testsuite/ PR fortran/122501 * gfortran.dg/pdt_66.f03: New test. PR fortran/122524 * gfortran.dg/pdt_67.f03: New test.
1 parent dd62c97 commit 071942e

File tree

3 files changed

+103
-27
lines changed

3 files changed

+103
-27
lines changed

gcc/fortran/primary.cc

Lines changed: 13 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -3543,7 +3543,7 @@ gfc_convert_to_structure_constructor (gfc_expr *e, gfc_symbol *sym, gfc_expr **c
35433543
}
35443544

35453545
/* Find the current component in the structure definition and check
3546-
its access is not private. */
3546+
its access is not private. */
35473547
if (comp)
35483548
this_comp = gfc_find_component (sym, comp->name, false, false, NULL);
35493549
else
@@ -3836,8 +3836,6 @@ gfc_match_rvalue (gfc_expr **result)
38363836
bool implicit_char;
38373837
gfc_ref *ref;
38383838
gfc_symtree *pdt_st;
3839-
gfc_symbol *found_specific = NULL;
3840-
38413839

38423840
m = gfc_match ("%%loc");
38433841
if (m == MATCH_YES)
@@ -4085,29 +4083,21 @@ gfc_match_rvalue (gfc_expr **result)
40854083
break;
40864084
}
40874085

4088-
gfc_gobble_whitespace ();
4089-
found_specific = NULL;
4090-
4091-
/* Even if 'name' is that of a PDT template, priority has to be given to
4092-
possible specific procedures in the generic interface. */
4093-
gfc_find_sym_tree (gfc_dt_upper_string (name), NULL, 1, &pdt_st);
4094-
if (sym->generic && sym->generic->next
4095-
&& gfc_peek_ascii_char() != '(')
4096-
{
4097-
gfc_actual_arglist *arg = actual_arglist;
4098-
for (; arg && pdt_st; arg = arg->next)
4099-
gfc_resolve_expr (arg->expr);
4100-
found_specific = gfc_search_interface (sym->generic, 0,
4101-
&actual_arglist);
4102-
}
4103-
41044086
/* Check to see if this is a PDT constructor. The format of these
41054087
constructors is rather unusual:
41064088
name [(type_params)](component_values)
41074089
where, component_values excludes the type_params. With the present
41084090
gfortran representation this is rather awkward because the two are not
4109-
distinguished, other than by their attributes. */
4110-
if (sym->attr.generic && pdt_st != NULL && found_specific == NULL)
4091+
distinguished, other than by their attributes.
4092+
4093+
Even if 'name' is that of a PDT template, priority has to be given to
4094+
specific procedures, other than the constructor, in the generic
4095+
interface. */
4096+
4097+
gfc_gobble_whitespace ();
4098+
gfc_find_sym_tree (gfc_dt_upper_string (name), NULL, 1, &pdt_st);
4099+
if (sym->attr.generic && pdt_st != NULL
4100+
&& !(sym->generic->next && gfc_peek_ascii_char() != '('))
41114101
{
41124102
gfc_symbol *pdt_sym;
41134103
gfc_actual_arglist *ctr_arglist = NULL, *tmp;
@@ -4172,12 +4162,8 @@ gfc_match_rvalue (gfc_expr **result)
41724162
tmp = tmp->next;
41734163
}
41744164

4175-
if (found_specific)
4176-
gfc_find_sym_tree (found_specific->name,
4177-
NULL, 1, &symtree);
4178-
else
4179-
gfc_find_sym_tree (gfc_dt_lower_string (pdt_sym->name),
4180-
NULL, 1, &symtree);
4165+
gfc_find_sym_tree (gfc_dt_lower_string (pdt_sym->name),
4166+
NULL, 1, &symtree);
41814167
if (!symtree)
41824168
{
41834169
gfc_get_ha_sym_tree (gfc_dt_lower_string (pdt_sym->name) ,
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
! { dg-do compile }
2+
! { dg-options "-fdump-tree-original" }
3+
!
4+
! Check the fix for PR122501.
5+
!
6+
! Contributed by Damian Rouson <damian@archaeologic.codes>
7+
!
8+
module tensor_m
9+
implicit none
10+
11+
type tensor_t(k)
12+
integer, kind :: k = kind(1.)
13+
real(k), allocatable, private :: values_(:)
14+
contains
15+
procedure default_real_values
16+
end type
17+
18+
interface tensor_t
19+
type(tensor_t) module function construct_default_real(values)
20+
implicit none
21+
real values(:)
22+
end function
23+
end interface
24+
25+
interface
26+
module function default_real_values(self) result(tensor_values)
27+
implicit none
28+
class(tensor_t) self
29+
real, allocatable :: tensor_values(:)
30+
end function
31+
end interface
32+
end module
33+
34+
use tensor_m
35+
implicit none
36+
contains
37+
function copy(tensor)
38+
type(tensor_t) tensor, copy, norm_copy
39+
associate(tensor_values => tensor%default_real_values())
40+
41+
! This gave: "Component ‘values_’ at (1) is a PRIVATE component of ‘tensor_t’"
42+
copy = tensor_t(tensor_values)
43+
44+
end associate
45+
46+
! Make sure that the fix really works :-)
47+
associate(f => tensor%default_real_values())
48+
associate(tensor_values => tensor%default_real_values())
49+
norm_copy = tensor_t(tensor_values/maxval(f))
50+
end associate
51+
end associate
52+
end function
53+
end
54+
! { dg-final { scan-tree-dump-times "default_real_values" 3 "original" } }
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
! { dg-do compile }
2+
!
3+
! Check the fix for PR122524.
4+
!
5+
! Contributed by Damian Rouson <damian@archaeologic.codes>
6+
!
7+
module tensor_map_m
8+
implicit none
9+
10+
type tensor_t(k)
11+
integer, kind :: k = kind(1.)
12+
real(k), allocatable :: values_(:)
13+
end type
14+
15+
interface tensor_t
16+
module function tensor(values)
17+
implicit none
18+
double precision values(:)
19+
type(tensor_t(kind(0D0))) tensor
20+
end function
21+
end interface
22+
23+
type tensor_map_t(k)
24+
integer, kind :: k = kind(1.)
25+
real(k) slope_
26+
end type
27+
28+
contains
29+
function unnormalized_tensor(self, tensor)
30+
type(tensor_map_t(kind(0D0))) self
31+
type(tensor_t(kind(0D0))) tensor, unnormalized_tensor
32+
associate(unnormalized_values => tensor%values_*self%slope_)
33+
unnormalized_tensor = tensor_t(unnormalized_values) ! Caused an ICE.
34+
end associate
35+
end function
36+
end module

0 commit comments

Comments
 (0)