@@ -56,9 +56,64 @@ static void CheckImplicitInterfaceArg(evaluate::ActualArgument &arg,
5656 " %VAL argument must be a scalar numeric or logical expression" _err_en_US);
5757 }
5858 if (const auto *expr{arg.UnwrapExpr ()}) {
59- if (const Symbol * base{GetFirstSymbol (*expr)};
60- base && IsFunctionResult (*base)) {
61- context.NoteDefinedSymbol (*base);
59+ if (const Symbol * base{GetFirstSymbol (*expr)}) {
60+ if (IsFunctionResult (*base)) {
61+ context.NoteDefinedSymbol (*base);
62+ } else {
63+ // passing global variables
64+ // here, arrays with subscripts are processing
65+ bool warn{false };
66+ std::string ownerName{" " };
67+ std::string ownerType{" " };
68+ if (base->flags ().test (Symbol::Flag::InCommonBlock)) {
69+ const Symbol *common{FindCommonBlockContaining (*base)};
70+ ownerType = " COMMON" ;
71+ ownerName = common->name ().ToString ();
72+ if (!(base->Rank () == 1 && base->offset () == 0 )) {
73+ warn |= true ;
74+ } else if (base->Rank () == 1 ) {
75+ if (const ArraySpec *dims{base->GetShape ()};
76+ dims && dims->IsExplicitShape ()) {
77+ if (!((*dims)[0 ].lbound ().GetExplicit () == (*dims)[0 ].ubound ().GetExplicit ())) {
78+ warn |= true ;
79+ }
80+ }
81+ if (common->get <CommonBlockDetails>().objects ().size () > 1 ) {
82+ warn |= true ;
83+ }
84+ }
85+ } else if (const auto &owner{base->GetUltimate ().owner ()};
86+ owner.IsModule () || owner.IsSubmodule ()) {
87+ const Scope *module {FindModuleContaining (owner)};
88+ ownerType = " MODULE" ;
89+ ownerName = module ->GetName ()->ToString ();
90+ if (base->attrs ().test (Attr::PARAMETER)) {
91+ warn |= false ;
92+ } else if (base->Rank () != 1 ) {
93+ warn |= true ;
94+ } else if (!base->attrs ().test (Attr::ALLOCATABLE) &&
95+ !base->attrs ().test (Attr::POINTER) &&
96+ !base->attrs ().test (Attr::VOLATILE)) {
97+ // by some reason, dims is not constructed here. For common blocks' variables, it works
98+ // it leads to three skipped tests
99+ /*
100+ if (const ArraySpec *dims{base->GetShape()};
101+ dims && dims->IsExplicitShape()) {
102+ if (!((*dims)[0].lbound().GetExplicit() == (*dims)[0].ubound().GetExplicit())) {
103+ warn |= true;
104+ }
105+ }
106+ */
107+ // just give some warnings in code where modules and implicit interfaces are mixed
108+ warn |= true ;
109+ }
110+ }
111+ if (warn) {
112+ context.Warn (common::UsageWarning::PassGlobalVariable, messages.at (),
113+ " Passing global variable '%s' from %s '%s' as function argument" _warn_en_US,
114+ base->name (), ownerType, ownerName);
115+ }
116+ }
62117 }
63118 if (IsBOZLiteral (*expr)) {
64119 messages.Say (" BOZ argument requires an explicit interface" _err_en_US);
@@ -79,6 +134,36 @@ static void CheckImplicitInterfaceArg(evaluate::ActualArgument &arg,
79134 messages.Say (
80135 " VOLATILE argument requires an explicit interface" _err_en_US);
81136 }
137+ // passing global variables
138+ // here, scalars and arrays without subscripts are processing
139+ bool warn{false };
140+ std::string ownerName{" " };
141+ std::string ownerType{" " };
142+ if (symbol.flags ().test (Symbol::Flag::InCommonBlock)) {
143+ const Symbol *common{FindCommonBlockContaining (symbol)};
144+ ownerType = " COMMON" ;
145+ ownerName = common->name ().ToString ();
146+ warn |= true ;
147+ } else if (const auto & owner{symbol.GetUltimate ().owner ()};
148+ owner.IsModule () || owner.IsSubmodule ()) {
149+ const Scope *module {FindModuleContaining (owner)};
150+ ownerType = " MODULE" ;
151+ ownerName = module ->GetName ()->ToString ();
152+ if (symbol.attrs ().test (Attr::PARAMETER)) {
153+ warn |= false ;
154+ } else if (symbol.Rank () != 1 ) {
155+ warn |= true ;
156+ } else if (!symbol.attrs ().test (Attr::ALLOCATABLE) &&
157+ !symbol.attrs ().test (Attr::POINTER) &&
158+ !symbol.attrs ().test (Attr::VOLATILE)) {
159+ warn |= true ;
160+ }
161+ }
162+ if (warn) {
163+ context.Warn (common::UsageWarning::PassGlobalVariable, messages.at (),
164+ " Passing global variable '%s' from %s '%s' as function argument" _warn_en_US,
165+ symbol.name (), ownerType, ownerName);
166+ }
82167 } else if (auto argChars{characteristics::DummyArgument::FromActual (
83168 " actual argument" , *expr, context.foldingContext (),
84169 /* forImplicitInterface=*/ true )}) {
0 commit comments