Skip to content

Commit 384b4e0

Browse files
committed
[flang] Fix error in characteristics check at procedure pointer assignment
If the procedure pointer has an explicit interface, its characteristics must equal the characteristics of its target, except that the target may be pure or elemental also when the pointer is not (cf. F2018 10.2.2.4(3)). In the semantics check for assignment of procedure pointers, the attributes of the procedures were not checked correctly due to a typo. This caused some illegal pointer-target-combinations to pass without raising an error. Fix this, and expand the test case to improve the coverage of procedure pointer assignment checks. Reviewed By: PeteSteinfeld Differential Revision: https://reviews.llvm.org/D113368
1 parent 2a88d00 commit 384b4e0

File tree

2 files changed

+102
-16
lines changed

2 files changed

+102
-16
lines changed

flang/lib/Evaluate/tools.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -911,12 +911,12 @@ std::optional<std::string> FindImpureCall(
911911
return FindImpureCallHelper{context}(proc);
912912
}
913913

914-
// Compare procedure characteristics for equality except that lhs may be
915-
// Pure or Elemental when rhs is not.
914+
// Compare procedure characteristics for equality except that rhs may be
915+
// Pure or Elemental when lhs is not.
916916
static bool CharacteristicsMatch(const characteristics::Procedure &lhs,
917917
const characteristics::Procedure &rhs) {
918918
using Attr = characteristics::Procedure::Attr;
919-
auto lhsAttrs{rhs.attrs};
919+
auto lhsAttrs{lhs.attrs};
920920
lhsAttrs.set(
921921
Attr::Pure, lhs.attrs.test(Attr::Pure) || rhs.attrs.test(Attr::Pure));
922922
lhsAttrs.set(Attr::Elemental,

flang/test/Semantics/assign03.f90

Lines changed: 99 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -63,26 +63,112 @@ subroutine s_module(i)
6363

6464
! 10.2.2.4(3)
6565
subroutine s5
66-
procedure(f_pure), pointer :: p_pure
67-
procedure(f_impure), pointer :: p_impure
66+
procedure(f_impure1), pointer :: p_impure
67+
procedure(f_pure1), pointer :: p_pure
6868
!ERROR: Procedure pointer 'p_elemental' may not be ELEMENTAL
69-
procedure(f_elemental), pointer :: p_elemental
70-
p_pure => f_pure
71-
p_impure => f_impure
72-
p_impure => f_pure
73-
!ERROR: PURE procedure pointer 'p_pure' may not be associated with non-PURE procedure designator 'f_impure'
74-
p_pure => f_impure
69+
procedure(f_elemental1), pointer :: p_elemental
70+
procedure(s_impure1), pointer :: sp_impure
71+
procedure(s_pure1), pointer :: sp_pure
72+
!ERROR: Procedure pointer 'sp_elemental' may not be ELEMENTAL
73+
procedure(s_elemental1), pointer :: sp_elemental
74+
75+
p_impure => f_impure1 ! OK, same characteristics
76+
p_impure => f_pure1 ! OK, target may be pure when pointer is not
77+
p_impure => f_elemental1 ! OK, target may be pure elemental
78+
p_impure => f_ImpureElemental1 ! OK, target may be elemental
79+
80+
sp_impure => s_impure1 ! OK, same characteristics
81+
sp_impure => s_pure1 ! OK, target may be pure when pointer is not
82+
sp_impure => s_elemental1 ! OK, target may be elemental when pointer is not
83+
84+
!ERROR: PURE procedure pointer 'p_pure' may not be associated with non-PURE procedure designator 'f_impure1'
85+
p_pure => f_impure1
86+
p_pure => f_pure1 ! OK, same characteristics
87+
p_pure => f_elemental1 ! OK, target may be pure
88+
!ERROR: PURE procedure pointer 'p_pure' may not be associated with non-PURE procedure designator 'f_impureelemental1'
89+
p_pure => f_impureElemental1
90+
91+
!ERROR: PURE procedure pointer 'sp_pure' may not be associated with non-PURE procedure designator 's_impure1'
92+
sp_pure => s_impure1
93+
sp_pure => s_pure1 ! OK, same characteristics
94+
sp_pure => s_elemental1 ! OK, target may be elemental when pointer is not
95+
96+
!ERROR: Procedure pointer 'p_impure' associated with incompatible procedure designator 'f_impure2'
97+
p_impure => f_impure2
98+
!ERROR: Procedure pointer 'p_pure' associated with incompatible procedure designator 'f_pure2'
99+
p_pure => f_pure2
100+
!ERROR: Procedure pointer 'p_impure' associated with incompatible procedure designator 'f_elemental2'
101+
p_impure => f_elemental2
102+
103+
!ERROR: Procedure pointer 'sp_impure' associated with incompatible procedure designator 's_impure2'
104+
sp_impure => s_impure2
105+
!ERROR: Procedure pointer 'sp_impure' associated with incompatible procedure designator 's_pure2'
106+
sp_impure => s_pure2
107+
!ERROR: Procedure pointer 'sp_pure' associated with incompatible procedure designator 's_elemental2'
108+
sp_pure => s_elemental2
109+
110+
!ERROR: Function pointer 'p_impure' may not be associated with subroutine designator 's_impure1'
111+
p_impure => s_impure1
112+
113+
!ERROR: Subroutine pointer 'sp_impure' may not be associated with function designator 'f_impure1'
114+
sp_impure => f_impure1
115+
75116
contains
76-
pure integer function f_pure()
77-
f_pure = 1
117+
integer function f_impure1(n)
118+
real, intent(in) :: n
119+
f_impure = n
120+
end
121+
pure integer function f_pure1(n)
122+
real, intent(in) :: n
123+
f_pure = n
78124
end
79-
integer function f_impure()
80-
f_impure = 1
125+
elemental integer function f_elemental1(n)
126+
real, intent(in) :: n
127+
f_elemental = n
128+
end
129+
impure elemental integer function f_impureElemental1(n)
130+
real, intent(in) :: n
131+
f_impureElemental = n
132+
end
133+
134+
integer function f_impure2(n)
135+
real, intent(inout) :: n
136+
f_impure = n
137+
end
138+
pure real function f_pure2(n)
139+
real, intent(in) :: n
140+
f_pure = n
81141
end
82-
elemental integer function f_elemental(n)
142+
elemental integer function f_elemental2(n)
83143
real, value :: n
84144
f_elemental = n
85145
end
146+
147+
subroutine s_impure1(n)
148+
integer, intent(inout) :: n
149+
n = n + 1
150+
end
151+
pure subroutine s_pure1(n)
152+
integer, intent(inout) :: n
153+
n = n + 1
154+
end
155+
elemental subroutine s_elemental1(n)
156+
integer, intent(inout) :: n
157+
n = n + 1
158+
end
159+
160+
subroutine s_impure2(n) bind(c)
161+
integer, intent(inout) :: n
162+
n = n + 1
163+
end subroutine s_impure2
164+
pure subroutine s_pure2(n)
165+
integer, intent(out) :: n
166+
n = 1
167+
end subroutine s_pure2
168+
elemental subroutine s_elemental2(m,n)
169+
integer, intent(inout) :: m, n
170+
n = m + n
171+
end subroutine s_elemental2
86172
end
87173

88174
! 10.2.2.4(4)

0 commit comments

Comments
 (0)