Skip to content

Commit d45672f

Browse files
committed
[flang] Silence errors on C_LOC/C_FUNLOC in specification expressions
Transformational functions from the intrinsic module ISO_C_BINDING are allowed in specification expressions, so tweak some general checks that would otherwise trigger error messages about inadmissible targets, dummy procedures in specification expressions, and pure procedures with impure dummy procedures.
1 parent 34a2889 commit d45672f

File tree

5 files changed

+25
-3
lines changed

5 files changed

+25
-3
lines changed

flang/lib/Evaluate/check-expression.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -649,7 +649,8 @@ class CheckSpecificationExprHelper
649649
return std::holds_alternative<characteristics::DummyProcedure>(
650650
dummy.u);
651651
})};
652-
if (iter != procChars->dummyArguments.end()) {
652+
if (iter != procChars->dummyArguments.end() &&
653+
ultimate.name().ToString() != "__builtin_c_funloc") {
653654
return "reference to function '"s + ultimate.name().ToString() +
654655
"' with dummy procedure argument '" + iter->name + '\'';
655656
}

flang/lib/Evaluate/tools.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,8 @@ auto IsVariableHelper::operator()(const Symbol &symbol) const -> Result {
8282
const Symbol &ultimate{symbol.GetUltimate()};
8383
return !IsNamedConstant(ultimate) &&
8484
(ultimate.has<semantics::ObjectEntityDetails>() ||
85+
(ultimate.has<semantics::EntityDetails>() &&
86+
ultimate.attrs().test(semantics::Attr::TARGET)) ||
8587
ultimate.has<semantics::AssocEntityDetails>());
8688
}
8789
auto IsVariableHelper::operator()(const Component &x) const -> Result {

flang/lib/Semantics/check-declarations.cpp

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -354,7 +354,10 @@ void CheckHelper::Check(const Symbol &symbol) {
354354
messages_.Say(
355355
"A pure subprogram may not have a variable with the VOLATILE attribute"_err_en_US);
356356
}
357-
if (IsProcedure(symbol) && !IsPureProcedure(symbol) && IsDummy(symbol)) {
357+
if (innermostSymbol_ && innermostSymbol_->name() == "__builtin_c_funloc") {
358+
// The intrinsic procedure C_FUNLOC() gets a pass on this check.
359+
} else if (IsProcedure(symbol) && !IsPureProcedure(symbol) &&
360+
IsDummy(symbol)) {
358361
messages_.Say(
359362
"A dummy procedure of a pure subprogram must be pure"_err_en_US);
360363
}

flang/module/__fortran_builtins.f90

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -182,7 +182,10 @@
182182
__builtin_c_ptr_ne = x%__address /= y%__address
183183
end function
184184

185-
function __builtin_c_funloc(x)
185+
! Semantics has some special-case code that allows c_funloc()
186+
! to appear in a specification expression and exempts it
187+
! from the requirement that "x" be a pure dummy procedure.
188+
pure function __builtin_c_funloc(x)
186189
type(__builtin_c_funptr) :: __builtin_c_funloc
187190
external :: x
188191
__builtin_c_funloc = __builtin_c_funptr(loc(x))

flang/test/Semantics/c_loc01.f90

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,10 @@ module m
44
type haslen(L)
55
integer, len :: L
66
end type
7+
integer, target :: targ
78
contains
9+
subroutine subr
10+
end
811
subroutine test(assumedType, poly, nclen)
912
type(*), target :: assumedType
1013
class(*), target :: poly
@@ -17,6 +20,8 @@ subroutine test(assumedType, poly, nclen)
1720
type(hasLen(1)), target :: clen
1821
type(hasLen(*)), target :: nclen
1922
character(2), target :: ch
23+
real :: arr1(purefun1(c_loc(targ))) ! ok
24+
real :: arr2(purefun2(c_funloc(subr))) ! ok
2025
!ERROR: C_LOC() argument must be a data pointer or target
2126
cp = c_loc(notATarget)
2227
!ERROR: C_LOC() argument must be a data pointer or target
@@ -44,4 +49,12 @@ subroutine test(assumedType, poly, nclen)
4449
!ERROR: No intrinsic or user-defined ASSIGNMENT(=) matches operand types TYPE(c_funptr) and TYPE(c_ptr)
4550
cfp = cp
4651
end
52+
pure integer function purefun1(p)
53+
type(c_ptr), intent(in) :: p
54+
purefun1 = 1
55+
end
56+
pure integer function purefun2(p)
57+
type(c_funptr), intent(in) :: p
58+
purefun2 = 1
59+
end
4760
end module

0 commit comments

Comments
 (0)