Skip to content

Commit b3026ba

Browse files
authored
[flang] Soften interoperability error when standard allows (#115092)
The standard doesn't require that an interoperable procedure's dummy arguments have interoperable derived types in some cases. Although nearly all extant Fortran compilers emit errors, some don't, and things should work; so reduce the current fatal error message to an optional portability warning. Fixes #115010.
1 parent aa68dd5 commit b3026ba

File tree

3 files changed

+29
-7
lines changed

3 files changed

+29
-7
lines changed

flang/include/flang/Evaluate/tools.h

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1103,8 +1103,7 @@ extern template semantics::UnorderedSymbolSet CollectCudaSymbols(
11031103
bool HasVectorSubscript(const Expr<SomeType> &);
11041104

11051105
// Utilities for attaching the location of the declaration of a symbol
1106-
// of interest to a message, if both pointers are non-null. Handles
1107-
// the case of USE association gracefully.
1106+
// of interest to a message. Handles the case of USE association gracefully.
11081107
parser::Message *AttachDeclaration(parser::Message &, const Symbol &);
11091108
parser::Message *AttachDeclaration(parser::Message *, const Symbol &);
11101109
template <typename MESSAGES, typename... A>

flang/lib/Semantics/check-declarations.cpp

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -147,7 +147,8 @@ class CheckHelper {
147147
void CheckProcedureAssemblyName(const Symbol &symbol);
148148
void CheckExplicitSave(const Symbol &);
149149
parser::Messages WhyNotInteroperableDerivedType(const Symbol &);
150-
parser::Messages WhyNotInteroperableObject(const Symbol &);
150+
parser::Messages WhyNotInteroperableObject(
151+
const Symbol &, bool allowNonInteroperableType = false);
151152
parser::Messages WhyNotInteroperableFunctionResult(const Symbol &);
152153
parser::Messages WhyNotInteroperableProcedure(const Symbol &, bool isError);
153154
void CheckBindC(const Symbol &);
@@ -3001,7 +3002,8 @@ parser::Messages CheckHelper::WhyNotInteroperableDerivedType(
30013002
return msgs;
30023003
}
30033004

3004-
parser::Messages CheckHelper::WhyNotInteroperableObject(const Symbol &symbol) {
3005+
parser::Messages CheckHelper::WhyNotInteroperableObject(
3006+
const Symbol &symbol, bool allowNonInteroperableType) {
30053007
parser::Messages msgs;
30063008
if (examinedByWhyNotInteroperable_.find(symbol) !=
30073009
examinedByWhyNotInteroperable_.end()) {
@@ -3037,8 +3039,13 @@ parser::Messages CheckHelper::WhyNotInteroperableObject(const Symbol &symbol) {
30373039
if (const auto *type{symbol.GetType()}) {
30383040
const auto *derived{type->AsDerived()};
30393041
if (derived && !derived->typeSymbol().attrs().test(Attr::BIND_C)) {
3040-
if (!context_.IsEnabled(
3041-
common::LanguageFeature::NonBindCInteroperability)) {
3042+
if (allowNonInteroperableType) { // portability warning only
3043+
evaluate::AttachDeclaration(
3044+
context_.Warn(common::UsageWarning::Portability, symbol.name(),
3045+
"The derived type of this interoperable object should be BIND(C)"_port_en_US),
3046+
derived->typeSymbol());
3047+
} else if (!context_.IsEnabled(
3048+
common::LanguageFeature::NonBindCInteroperability)) {
30423049
msgs.Say(symbol.name(),
30433050
"The derived type of an interoperable object must be BIND(C)"_err_en_US)
30443051
.Attach(derived->typeSymbol().name(), "Non-BIND(C) type"_en_US);
@@ -3178,7 +3185,13 @@ parser::Messages CheckHelper::WhyNotInteroperableProcedure(
31783185
"A dummy procedure of an interoperable procedure should be BIND(C)"_warn_en_US);
31793186
}
31803187
} else if (dummy->has<ObjectEntityDetails>()) {
3181-
dummyMsgs = WhyNotInteroperableObject(*dummy);
3188+
// Emit only optional portability warnings for non-interoperable
3189+
// types when the dummy argument is not VALUE and will be implemented
3190+
// on the C side by either a cdesc_t * or a void *. F'2023 18.3.7 (5)
3191+
bool allowNonInteroperableType{!dummy->attrs().test(Attr::VALUE) &&
3192+
(IsDescriptor(*dummy) || IsAssumedType(*dummy))};
3193+
dummyMsgs =
3194+
WhyNotInteroperableObject(*dummy, allowNonInteroperableType);
31823195
} else {
31833196
CheckBindC(*dummy);
31843197
}

flang/test/Semantics/bind-c17.f90

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
! RUN: %python %S/test_errors.py %s %flang_fc1 -pedantic -Werror
2+
module m
3+
type a ! not BIND(C)
4+
end type
5+
contains
6+
subroutine sub(x) bind(c)
7+
!PORTABILITY: The derived type of this interoperable object should be BIND(C)
8+
type(a), pointer, intent(in) :: x
9+
end
10+
end

0 commit comments

Comments
 (0)