@@ -147,7 +147,8 @@ class CheckHelper {
147
147
void CheckProcedureAssemblyName (const Symbol &symbol);
148
148
void CheckExplicitSave (const Symbol &);
149
149
parser::Messages WhyNotInteroperableDerivedType (const Symbol &);
150
- parser::Messages WhyNotInteroperableObject (const Symbol &);
150
+ parser::Messages WhyNotInteroperableObject (
151
+ const Symbol &, bool allowNonInteroperableType = false );
151
152
parser::Messages WhyNotInteroperableFunctionResult (const Symbol &);
152
153
parser::Messages WhyNotInteroperableProcedure (const Symbol &, bool isError);
153
154
void CheckBindC (const Symbol &);
@@ -3001,7 +3002,8 @@ parser::Messages CheckHelper::WhyNotInteroperableDerivedType(
3001
3002
return msgs;
3002
3003
}
3003
3004
3004
- parser::Messages CheckHelper::WhyNotInteroperableObject (const Symbol &symbol) {
3005
+ parser::Messages CheckHelper::WhyNotInteroperableObject (
3006
+ const Symbol &symbol, bool allowNonInteroperableType) {
3005
3007
parser::Messages msgs;
3006
3008
if (examinedByWhyNotInteroperable_.find (symbol) !=
3007
3009
examinedByWhyNotInteroperable_.end ()) {
@@ -3037,8 +3039,13 @@ parser::Messages CheckHelper::WhyNotInteroperableObject(const Symbol &symbol) {
3037
3039
if (const auto *type{symbol.GetType ()}) {
3038
3040
const auto *derived{type->AsDerived ()};
3039
3041
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)) {
3042
3049
msgs.Say (symbol.name (),
3043
3050
" The derived type of an interoperable object must be BIND(C)" _err_en_US)
3044
3051
.Attach (derived->typeSymbol ().name (), " Non-BIND(C) type" _en_US);
@@ -3178,7 +3185,13 @@ parser::Messages CheckHelper::WhyNotInteroperableProcedure(
3178
3185
" A dummy procedure of an interoperable procedure should be BIND(C)" _warn_en_US);
3179
3186
}
3180
3187
} 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);
3182
3195
} else {
3183
3196
CheckBindC (*dummy);
3184
3197
}
0 commit comments