Skip to content

Commit 3c130e4

Browse files
committed
Fortran: fix checking of protected variables in submodules [PR83135]
When a symbol was use-associated in the ancestor of a submodule, a PROTECTED attribute was ignored in the submodule or its descendants. Find the real ancestor of symbols when used in a variable definition context in a submodule. PR fortran/83135 gcc/fortran/ChangeLog: * expr.cc (sym_is_from_ancestor): New helper function. (gfc_check_vardef_context): Refine checking of PROTECTED attribute of symbols that are indirectly use-associated in a submodule. gcc/testsuite/ChangeLog: * gfortran.dg/protected_10.f90: New test.
1 parent d5cebf7 commit 3c130e4

File tree

2 files changed

+110
-5
lines changed

2 files changed

+110
-5
lines changed

gcc/fortran/expr.cc

Lines changed: 35 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6272,6 +6272,33 @@ gfc_build_intrinsic_call (gfc_namespace *ns, gfc_isym_id id, const char* name,
62726272
}
62736273

62746274

6275+
/* Check if a symbol referenced in a submodule is declared in the ancestor
6276+
module and not accessed by use-association, and that the submodule is a
6277+
descendant. */
6278+
6279+
static bool
6280+
sym_is_from_ancestor (gfc_symbol *sym)
6281+
{
6282+
const char dot[2] = ".";
6283+
/* Symbols take the form module.submodule_ or module.name_. */
6284+
char ancestor_module[2 * GFC_MAX_SYMBOL_LEN + 2];
6285+
char *ancestor;
6286+
6287+
if (sym == NULL
6288+
|| sym->attr.use_assoc
6289+
|| !sym->attr.used_in_submodule
6290+
|| !sym->module
6291+
|| !sym->ns->proc_name
6292+
|| !sym->ns->proc_name->name)
6293+
return false;
6294+
6295+
memset (ancestor_module, '\0', sizeof (ancestor_module));
6296+
strcpy (ancestor_module, sym->ns->proc_name->name);
6297+
ancestor = strtok (ancestor_module, dot);
6298+
return strcmp (ancestor, sym->module) == 0;
6299+
}
6300+
6301+
62756302
/* Check if an expression may appear in a variable definition context
62766303
(F2008, 16.6.7) or pointer association context (F2008, 16.6.8).
62776304
This is called from the various places when resolving
@@ -6450,21 +6477,24 @@ gfc_check_vardef_context (gfc_expr* e, bool pointer, bool alloc_obj,
64506477
}
64516478

64526479
/* PROTECTED and use-associated. */
6453-
if (sym->attr.is_protected && sym->attr.use_assoc && check_intentin)
6480+
if (sym->attr.is_protected
6481+
&& (sym->attr.use_assoc
6482+
|| (sym->attr.used_in_submodule && !sym_is_from_ancestor (sym)))
6483+
&& check_intentin)
64546484
{
64556485
if (pointer && is_pointer)
64566486
{
64576487
if (context)
6458-
gfc_error ("Variable %qs is PROTECTED and cannot appear in a"
6459-
" pointer association context (%s) at %L",
6488+
gfc_error ("Variable %qs is PROTECTED and cannot appear in a "
6489+
"pointer association context (%s) at %L",
64606490
sym->name, context, &e->where);
64616491
return false;
64626492
}
64636493
if (!pointer && !is_pointer)
64646494
{
64656495
if (context)
6466-
gfc_error ("Variable %qs is PROTECTED and cannot appear in a"
6467-
" variable definition context (%s) at %L",
6496+
gfc_error ("Variable %qs is PROTECTED and cannot appear in a "
6497+
"variable definition context (%s) at %L",
64686498
sym->name, context, &e->where);
64696499
return false;
64706500
}
Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
! { dg-do compile }
2+
! PR fortran/83135 - fix checking of protected variables in submodules
3+
4+
module mod1
5+
implicit none
6+
private
7+
integer, protected, public :: xx = 42
8+
public :: set_xx
9+
public :: echo1_xx, echo2_xx
10+
interface
11+
module subroutine echo1_xx()
12+
end subroutine echo1_xx
13+
module subroutine echo2_xx()
14+
end subroutine echo2_xx
15+
end interface
16+
contains
17+
subroutine set_xx(arg)
18+
integer, intent(in) :: arg
19+
xx = arg ! valid (it is host_associated)
20+
end
21+
end module
22+
!
23+
submodule (mod1) s1mod1
24+
implicit none
25+
contains
26+
module subroutine echo1_xx()
27+
xx = 11 ! valid (it is from the ancestor)
28+
write(*,*) "xx=", xx
29+
end subroutine echo1_xx
30+
end submodule
31+
!
32+
submodule (mod1:s1mod1) s2mod1
33+
implicit none
34+
contains
35+
module subroutine echo2_xx()
36+
xx = 12 ! valid (it is from the ancestor)
37+
write(*,*) "xx=", xx
38+
end subroutine echo2_xx
39+
end submodule
40+
!
41+
module mod2
42+
use mod1
43+
implicit none
44+
integer, protected, public :: yy = 43
45+
interface
46+
module subroutine echo_xx()
47+
end subroutine echo_xx
48+
end interface
49+
contains
50+
subroutine bla
51+
! xx = 999 ! detected, leads to fatal error
52+
end
53+
end module
54+
!
55+
submodule (mod2) smod2
56+
implicit none
57+
contains
58+
module subroutine echo_xx ()
59+
xx = 10 ! { dg-error "is PROTECTED" }
60+
write(*,*) "xx=", xx
61+
yy = 22 ! valid (it is from the ancestor)
62+
end
63+
end submodule
64+
!
65+
program test_protected
66+
use mod1
67+
use mod2
68+
implicit none
69+
write(*,*) "xx=", xx
70+
call set_xx(88)
71+
write(*,*) "xx=", xx
72+
call echo_xx
73+
call echo1_xx
74+
call echo2_xx
75+
end program

0 commit comments

Comments
 (0)