Skip to content

Commit 2d6e280

Browse files
committed
[flang] Support C1553 about BIND(C) function result
As Fortran 2018 C1553, if with BIND(C), the function result shall be an interoperable scalar variable. As Fortran 2018 18.3.4(1), the interoperable scalar variable is not a coarray, has neither the ALLOCATABLE nor the POINTER attribute, and if it is of type character its length is not assumed or declared by an expression that is not a constant expression. As Fortran 2018 18.3.1(1), if the type is character, the length type parameter is interoperable if and only if its value is one. Reviewed By: PeteSteinfeld, jeanPerier Differential Revision: https://reviews.llvm.org/D137254
1 parent 800f0f1 commit 2d6e280

File tree

2 files changed

+80
-0
lines changed

2 files changed

+80
-0
lines changed

flang/lib/Semantics/check-declarations.cpp

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,7 @@ class CheckHelper {
114114
}
115115
bool IsResultOkToDiffer(const FunctionResult &);
116116
void CheckBindC(const Symbol &);
117+
void CheckBindCFunctionResult(const Symbol &);
117118
// Check functions for defined I/O procedures
118119
void CheckDefinedIoProc(
119120
const Symbol &, const GenericDetails &, GenericKind::DefinedIo);
@@ -399,6 +400,7 @@ void CheckHelper::Check(const Symbol &symbol) {
399400
messages_.Say(
400401
"A function result may not have the SAVE attribute"_err_en_US);
401402
}
403+
CheckBindCFunctionResult(symbol);
402404
}
403405
if (symbol.owner().IsDerivedType() &&
404406
(symbol.attrs().test(Attr::CONTIGUOUS) &&
@@ -416,6 +418,35 @@ void CheckHelper::Check(const Symbol &symbol) {
416418

417419
void CheckHelper::CheckCommonBlock(const Symbol &symbol) { CheckBindC(symbol); }
418420

421+
void CheckHelper::CheckBindCFunctionResult(const Symbol &symbol) { // C1553
422+
if (!innermostSymbol_ || !IsBindCProcedure(*innermostSymbol_)) {
423+
return;
424+
}
425+
if (IsPointer(symbol) || IsAllocatable(symbol)) {
426+
messages_.Say(
427+
"BIND(C) function result cannot have ALLOCATABLE or POINTER attribute"_err_en_US);
428+
}
429+
if (const DeclTypeSpec * type{symbol.GetType()};
430+
type && type->category() == DeclTypeSpec::Character) {
431+
bool isConstOne{false}; // 18.3.1(1)
432+
if (const auto &len{type->characterTypeSpec().length().GetExplicit()}) {
433+
if (auto constLen{evaluate::ToInt64(*len)}) {
434+
isConstOne = constLen == 1;
435+
}
436+
}
437+
if (!isConstOne) {
438+
messages_.Say(
439+
"BIND(C) character function result must have length one"_err_en_US);
440+
}
441+
}
442+
if (symbol.Rank() > 0) {
443+
messages_.Say("BIND(C) function result must be scalar"_err_en_US);
444+
}
445+
if (symbol.Corank()) {
446+
messages_.Say("BIND(C) function result cannot be a coarray"_err_en_US);
447+
}
448+
}
449+
419450
void CheckHelper::CheckValue(
420451
const Symbol &symbol, const DerivedTypeSpec *derived) { // C863 - C865
421452
if (!IsDummy(symbol)) {

flang/test/Semantics/bind-c09.f90

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
! RUN: %python %S/test_errors.py %s %flang_fc1
2+
! Check for C1553 and 18.3.4(1)
3+
4+
function func1() result(res) bind(c)
5+
! ERROR: BIND(C) function result cannot have ALLOCATABLE or POINTER attribute
6+
integer, pointer :: res
7+
end
8+
9+
function func2() result(res) bind(c)
10+
! ERROR: BIND(C) function result cannot have ALLOCATABLE or POINTER attribute
11+
integer, allocatable :: res
12+
end
13+
14+
function func3() result(res) bind(c)
15+
! ERROR: BIND(C) function result must be scalar
16+
integer :: res(2)
17+
end
18+
19+
function func4() result(res) bind(c)
20+
! ERROR: BIND(C) character function result must have length one
21+
character(*) :: res
22+
end
23+
24+
function func5(n) result(res) bind(c)
25+
integer :: n
26+
! ERROR: BIND(C) character function result must have length one
27+
character(n) :: res
28+
end
29+
30+
function func6() result(res) bind(c)
31+
! ERROR: BIND(C) character function result must have length one
32+
character(2) :: res
33+
end
34+
35+
function func7() result(res) bind(c)
36+
integer, parameter :: n = 1
37+
character(n) :: res ! OK
38+
end
39+
40+
function func8() result(res) bind(c)
41+
! ERROR: BIND(C) function result cannot have ALLOCATABLE or POINTER attribute
42+
! ERROR: BIND(C) character function result must have length one
43+
character(:), pointer :: res
44+
end
45+
46+
function func9() result(res) bind(c)
47+
! ERROR: BIND(C) function result cannot be a coarray
48+
integer :: res[10, *]
49+
end

0 commit comments

Comments
 (0)