@@ -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 }
0 commit comments