Skip to content

Commit 463f58a

Browse files
authored
[flang] Further work on relaxing BIND(C) enforcement (llvm#92029)
When a BIND(C) interface or subprogram has a dummy argument whose derived type is not BIND(C) but meets the constraints and requirements of a BIND(C) type, accept it with a warning.
1 parent 7605ad8 commit 463f58a

File tree

2 files changed

+56
-5
lines changed

2 files changed

+56
-5
lines changed

flang/lib/Semantics/check-declarations.cpp

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2891,7 +2891,8 @@ parser::Messages CheckHelper::WhyNotInteroperableDerivedType(
28912891
} else {
28922892
bool interoperableParent{true};
28932893
if (parent->symbol()) {
2894-
auto bad{WhyNotInteroperableDerivedType(*parent->symbol(), false)};
2894+
auto bad{WhyNotInteroperableDerivedType(
2895+
*parent->symbol(), /*isError=*/false)};
28952896
if (bad.AnyFatalError()) {
28962897
auto &msg{msgs.Say(symbol.name(),
28972898
"The parent of an interoperable type is not interoperable"_err_en_US)};
@@ -2981,6 +2982,9 @@ parser::Messages CheckHelper::WhyNotInteroperableDerivedType(
29812982
}
29822983
}
29832984
}
2985+
if (msgs.AnyFatalError()) {
2986+
examinedByWhyNotInteroperableDerivedType_.erase(symbol);
2987+
}
29842988
return msgs;
29852989
}
29862990

@@ -3068,16 +3072,18 @@ void CheckHelper::CheckBindC(const Symbol &symbol) {
30683072
}
30693073
context_.SetError(symbol);
30703074
} else if (auto bad{WhyNotInteroperableDerivedType(
3071-
derived->typeSymbol(), false)};
3072-
!bad.empty()) {
3075+
derived->typeSymbol(), /*isError=*/false)};
3076+
bad.AnyFatalError()) {
30733077
if (auto *msg{messages_.Say(symbol.name(),
30743078
"The derived type of an interoperable object must be interoperable, but is not"_err_en_US)}) {
30753079
msg->Attach(
30763080
derived->typeSymbol().name(), "Non-interoperable type"_en_US);
30773081
bad.AttachTo(*msg, parser::Severity::None);
30783082
}
30793083
context_.SetError(symbol);
3080-
} else {
3084+
} else if (context_.ShouldWarn(
3085+
common::LanguageFeature::NonBindCInteroperability) &&
3086+
!InModuleFile()) {
30813087
if (auto *msg{messages_.Say(symbol.name(),
30823088
"The derived type of an interoperable object should be BIND(C)"_warn_en_US)}) {
30833089
msg->Attach(derived->typeSymbol().name(), "Non-BIND(C) type"_en_US);
@@ -3151,7 +3157,7 @@ void CheckHelper::CheckBindC(const Symbol &symbol) {
31513157
}
31523158
}
31533159
} else if (symbol.has<DerivedTypeDetails>()) {
3154-
if (auto msgs{WhyNotInteroperableDerivedType(symbol, false)};
3160+
if (auto msgs{WhyNotInteroperableDerivedType(symbol, /*isError=*/false)};
31553161
!msgs.empty()) {
31563162
bool anyFatal{msgs.AnyFatalError()};
31573163
if (msgs.AnyFatalError() ||

flang/test/Semantics/bind-c15.f90

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
! RUN: %python %S/test_errors.py %s %flang_fc1 -pedantic
2+
3+
module m
4+
type, bind(c) :: explicit_bind_c
5+
real a
6+
end type
7+
type :: interoperable1
8+
type(explicit_bind_c) a
9+
end type
10+
type, extends(interoperable1) :: interoperable2
11+
real b
12+
end type
13+
type :: non_interoperable1
14+
real, allocatable :: a
15+
end type
16+
type :: non_interoperable2
17+
type(non_interoperable1) b
18+
end type
19+
interface
20+
subroutine sub_bind_c_1(x_bind_c) bind(c)
21+
import explicit_bind_c
22+
type(explicit_bind_c), intent(in) :: x_bind_c
23+
end
24+
subroutine sub_bind_c_2(x_interop1) bind(c)
25+
import interoperable1
26+
!WARNING: The derived type of an interoperable object should be BIND(C)
27+
type(interoperable1), intent(in) :: x_interop1
28+
end
29+
subroutine sub_bind_c_3(x_interop2) bind(c)
30+
import interoperable2
31+
!WARNING: The derived type of an interoperable object should be BIND(C)
32+
type(interoperable2), intent(in) :: x_interop2
33+
end
34+
subroutine sub_bind_c_4(x_non_interop1) bind(c)
35+
import non_interoperable1
36+
!ERROR: The derived type of an interoperable object must be interoperable, but is not
37+
type(non_interoperable1), intent(in) :: x_non_interop1
38+
end
39+
subroutine sub_bind_c_5(x_non_interop2) bind(c)
40+
import non_interoperable2
41+
!ERROR: The derived type of an interoperable object must be interoperable, but is not
42+
type(non_interoperable2), intent(in) :: x_non_interop2
43+
end
44+
end interface
45+
end

0 commit comments

Comments
 (0)