@@ -248,19 +248,108 @@ ProcedureRef::~ProcedureRef() {}
248248
249249void ProcedureRef::Deleter (ProcedureRef *p) { delete p; }
250250
251+ // We don't know the dummy argument info (e.g., procedure with implicit
252+ // interface
253+ static void DetermineCopyInOutArgument (
254+ const characteristics::Procedure &procInfo, ActualArgument &actual,
255+ semantics::SemanticsContext &sc) {
256+ if (actual.isAlternateReturn ()) {
257+ return ;
258+ }
259+ if (!evaluate::IsVariable (actual)) {
260+ // Actual argument expressions that aren’t variables are copy-in, but
261+ // not copy-out.
262+ actual.set_mayNeedCopyIn ();
263+ } else if (!IsSimplyContiguous (actual, sc.foldingContext ())) {
264+ // Actual arguments that are variables are copy-in when non-contiguous.
265+ // They are copy-out when don't have vector subscripts
266+ actual.set_mayNeedCopyIn ();
267+ if (!HasVectorSubscript (actual)) {
268+ actual.set_mayNeedCopyOut ();
269+ }
270+ } else if (ExtractCoarrayRef (actual)) {
271+ // Coindexed actual args need copy-in and copy-out
272+ actual.set_mayNeedCopyIn ();
273+ actual.set_mayNeedCopyOut ();
274+ }
275+ }
276+
277+ static void DetermineCopyInOutArgument (
278+ const characteristics::Procedure &procInfo, ActualArgument &actual,
279+ characteristics::DummyArgument &dummy, semantics::SemanticsContext &sc) {
280+ assert (procInfo.HasExplicitInterface () && " expect explicit interface proc" );
281+ if (actual.isAlternateReturn ()) {
282+ return ;
283+ }
284+ // TODO
285+ }
286+
251287void ProcedureRef::DetermineCopyInOut () {
252- if (!proc () .GetSymbol ()) {
288+ if (!proc_ .GetSymbol ()) {
253289 return ;
254290 }
255291 // Get folding context of the call site owner
256- FoldingContext &fc{proc_.GetSymbol ()->owner ().context ().foldingContext ()};
257- auto procInfo{characteristics::Procedure::Characterize (
258- proc_, fc, /* emitError=*/ true )};
292+ semantics::SemanticsContext &sc{proc_.GetSymbol ()->owner ().context ()};
293+ FoldingContext &fc{sc.foldingContext ()};
294+ auto procInfo{
295+ characteristics::Procedure::Characterize (proc_, fc, /* emitError=*/ true )};
259296 if (!procInfo) {
260297 return ;
261298 }
262- // TODO: at this point have dummy arguments as procInfo->dummyArguments
263- // and have actual arguments via arguments_
299+ if (!procInfo->HasExplicitInterface ()) {
300+ for (auto &actual : arguments_) {
301+ if (!actual) {
302+ continue ;
303+ }
304+ DetermineCopyInOutArgument (*procInfo, *actual, sc);
305+ }
306+ return ;
307+ }
308+ // Don't change anything about actual or dummy arguments, except for
309+ // computing copy-in/copy-out information. If detect something wrong with
310+ // the arguments, stop processing and let semantic analysis generate the
311+ // error messages.
312+ size_t index{0 };
313+ std::set<std::string> processedKeywords;
314+ bool seenKeyword{false };
315+ for (auto &actual : arguments_) {
316+ if (!actual) {
317+ continue ;
318+ }
319+ if (index >= procInfo->dummyArguments .size ()) {
320+ // More actual arguments than dummy arguments. Semantic analysis will
321+ // deal with the error.
322+ return ;
323+ }
324+ if (actual->keyword ()) {
325+ seenKeyword = true ;
326+ auto actualName = actual->keyword ()->ToString ();
327+ if (processedKeywords.find (actualName) != processedKeywords.end ()) {
328+ // Actual arguments with duplicate keywords. Semantic analysis will
329+ // deal with the error.
330+ return ;
331+ } else {
332+ processedKeywords.insert (actualName);
333+ if (auto it = std::find_if (procInfo->dummyArguments .begin (),
334+ procInfo->dummyArguments .end (),
335+ [&](const characteristics::DummyArgument &dummy) {
336+ return dummy.name == actualName;
337+ });
338+ it != procInfo->dummyArguments .end ()) {
339+ DetermineCopyInOutArgument (*procInfo, *actual, *it, sc);
340+ }
341+ }
342+ } else if (seenKeyword) {
343+ // Non-keyword actual argument after have seen at least one keyword
344+ // actual argument. Semantic analysis will deal with the error.
345+ return ;
346+ } else {
347+ // Positional argument processing
348+ DetermineCopyInOutArgument (
349+ *procInfo, *actual, procInfo->dummyArguments [index], sc);
350+ }
351+ ++index;
352+ }
264353}
265354
266355} // namespace Fortran::evaluate
0 commit comments