@@ -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 &);
@@ -2999,7 +3000,8 @@ parser::Messages CheckHelper::WhyNotInteroperableDerivedType(
29993000 return msgs;
30003001}
30013002
3002- parser::Messages CheckHelper::WhyNotInteroperableObject (const Symbol &symbol) {
3003+ parser::Messages CheckHelper::WhyNotInteroperableObject (
3004+ const Symbol &symbol, bool allowNonInteroperableType) {
30033005 parser::Messages msgs;
30043006 if (examinedByWhyNotInteroperable_.find (symbol) !=
30053007 examinedByWhyNotInteroperable_.end ()) {
@@ -3035,14 +3037,19 @@ parser::Messages CheckHelper::WhyNotInteroperableObject(const Symbol &symbol) {
30353037 if (const auto *type{symbol.GetType ()}) {
30363038 const auto *derived{type->AsDerived ()};
30373039 if (derived && !derived->typeSymbol ().attrs ().test (Attr::BIND_C)) {
3038- if (!context_.IsEnabled (
3039- common::LanguageFeature::NonBindCInteroperability)) {
3040+ if (allowNonInteroperableType) { // portability warning only
3041+ evaluate::AttachDeclaration (
3042+ context_.Warn (common::UsageWarning::Portability, symbol.name (),
3043+ " The derived type of this interoperable object should be BIND(C)" _port_en_US),
3044+ derived->typeSymbol ());
3045+ } else if (!context_.IsEnabled (
3046+ common::LanguageFeature::NonBindCInteroperability)) {
30403047 msgs.Say (symbol.name (),
30413048 " The derived type of an interoperable object must be BIND(C)" _err_en_US)
30423049 .Attach (derived->typeSymbol ().name (), " Non-BIND(C) type" _en_US);
30433050 } else if (auto bad{
30443051 WhyNotInteroperableDerivedType (derived->typeSymbol ())};
3045- bad.AnyFatalError ()) {
3052+ bad.AnyFatalError ()) {
30463053 bad.AttachTo (
30473054 msgs.Say (symbol.name (),
30483055 " The derived type of an interoperable object must be interoperable, but is not" _err_en_US)
@@ -3176,7 +3183,13 @@ parser::Messages CheckHelper::WhyNotInteroperableProcedure(
31763183 " A dummy procedure of an interoperable procedure should be BIND(C)" _warn_en_US);
31773184 }
31783185 } else if (dummy->has <ObjectEntityDetails>()) {
3179- dummyMsgs = WhyNotInteroperableObject (*dummy);
3186+ // Emit only optional portability warnings for non-interoperable
3187+ // types when the dummy argument is not VALUE and will be implemented
3188+ // on the C side by either a cdesc_t * or a void *. F'2023 18.3.7 (5)
3189+ bool allowNonInteroperableType{!dummy->attrs ().test (Attr::VALUE) &&
3190+ (IsDescriptor (*dummy) || IsAssumedType (*dummy))};
3191+ dummyMsgs =
3192+ WhyNotInteroperableObject (*dummy, allowNonInteroperableType);
31803193 } else {
31813194 CheckBindC (*dummy);
31823195 }
0 commit comments