|
12 | 12 | #include "flang/Evaluate/check-expression.h" |
13 | 13 | #include "flang/Evaluate/expression.h" |
14 | 14 | #include "flang/Evaluate/tools.h" |
15 | | -#include "flang/Semantics/semantics.h" |
16 | 15 | #include "flang/Semantics/symbol.h" |
17 | 16 | #include "flang/Support/Fortran.h" |
18 | 17 |
|
@@ -248,199 +247,4 @@ ProcedureRef::~ProcedureRef() {} |
248 | 247 |
|
249 | 248 | void ProcedureRef::Deleter(ProcedureRef *p) { delete p; } |
250 | 249 |
|
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.SetMayNeedCopyIn(); |
263 | | - } else if (bool actualIsArray{actual.Rank() > 0}; |
264 | | - actualIsArray && !IsSimplyContiguous(actual, sc.foldingContext())) { |
265 | | - // Actual arguments that are variables are copy-in when non-contiguous. |
266 | | - // They are copy-out when don't have vector subscripts |
267 | | - actual.SetMayNeedCopyIn(); |
268 | | - if (!HasVectorSubscript(actual)) { |
269 | | - actual.SetMayNeedCopyOut(); |
270 | | - } |
271 | | - } else if (ExtractCoarrayRef(actual)) { |
272 | | - // Coindexed actual args need copy-in and copy-out |
273 | | - actual.SetMayNeedCopyIn(); |
274 | | - actual.SetMayNeedCopyOut(); |
275 | | - } |
276 | | -} |
277 | | - |
278 | | -static void DetermineCopyInOutArgument( |
279 | | - const characteristics::Procedure &procInfo, ActualArgument &actual, |
280 | | - characteristics::DummyArgument &dummy, semantics::SemanticsContext &sc) { |
281 | | - assert(procInfo.HasExplicitInterface() && "expect explicit interface proc"); |
282 | | - if (actual.isAlternateReturn()) { |
283 | | - return; |
284 | | - } |
285 | | - if (!evaluate::IsVariable(actual)) { |
286 | | - // Actual argument expressions that aren’t variables are copy-in, but |
287 | | - // not copy-out. |
288 | | - actual.SetMayNeedCopyIn(); |
289 | | - return; |
290 | | - } |
291 | | - const auto *dummyObj{std::get_if<characteristics::DummyDataObject>(&dummy.u)}; |
292 | | - if (!dummyObj) { |
293 | | - // Only DummyDataObject has the information we need |
294 | | - return; |
295 | | - } |
296 | | - // Pass by value, always copy-in, never copy-out |
297 | | - bool dummyIsValue{ |
298 | | - dummyObj->attrs.test(characteristics::DummyDataObject::Attr::Value)}; |
299 | | - if (dummyIsValue) { |
300 | | - actual.SetMayNeedCopyIn(); |
301 | | - return; |
302 | | - } |
303 | | - // All the checks below are for arrays |
304 | | - |
305 | | - bool actualIsAssumedRank{evaluate::IsAssumedRank(actual)}; |
306 | | - bool actualIsArray{actualIsAssumedRank || actual.Rank() > 0}; |
307 | | - bool dummyIsAssumedRank{dummyObj->type.attrs().test( |
308 | | - characteristics::TypeAndShape::Attr::AssumedRank)}; |
309 | | - bool dummyIsArray{dummyIsAssumedRank || dummyObj->type.Rank() > 0}; |
310 | | - bool treatDummyScalarAsArray{dummyObj->type.Rank() == 0 && |
311 | | - dummyObj->ignoreTKR.test(common::IgnoreTKR::Rank)}; |
312 | | - if (!actualIsArray || !(dummyIsArray || treatDummyScalarAsArray)) { |
313 | | - return; |
314 | | - } |
315 | | - |
316 | | - bool dummyIntentIn{dummyObj->intent == common::Intent::In}; |
317 | | - bool dummyIntentOut{dummyObj->intent == common::Intent::Out}; |
318 | | - auto setCopyIn = [&]() { |
319 | | - if (!dummyIntentOut) { |
320 | | - // INTENT(OUT) dummy args never need copy-in |
321 | | - actual.SetMayNeedCopyIn(); |
322 | | - } |
323 | | - }; |
324 | | - auto setCopyOut = [&]() { |
325 | | - if (!dummyIntentIn) { |
326 | | - // INTENT(IN) dummy args never need copy-out |
327 | | - actual.SetMayNeedCopyOut(); |
328 | | - } |
329 | | - }; |
330 | | - |
331 | | - // Check actual contiguity, unless dummy doesn't care |
332 | | - bool actualTreatAsContiguous{ |
333 | | - dummyObj->ignoreTKR.test(common::IgnoreTKR::Contiguous) || |
334 | | - IsSimplyContiguous(actual, sc.foldingContext())}; |
335 | | - bool actualHasVectorSubscript{HasVectorSubscript(actual)}; |
336 | | - bool dummyIsExplicitShape{dummyObj->type.IsExplicitShape()}; |
337 | | - bool dummyIsAssumedSize{dummyObj->type.attrs().test( |
338 | | - characteristics::TypeAndShape::Attr::AssumedSize)}; |
339 | | - bool dummyIsPolymorphic{dummyObj->type.type().IsPolymorphic()}; |
340 | | - // Explicit shape and assumed size arrays must be contiguous |
341 | | - bool dummyNeedsContiguity{dummyIsExplicitShape || dummyIsAssumedSize || |
342 | | - // Polymorphic dummy is descriptor based, so should be able to handle |
343 | | - // discontigunity. |
344 | | - (treatDummyScalarAsArray && !dummyIsPolymorphic) || |
345 | | - dummyObj->attrs.test(characteristics::DummyDataObject::Attr::Contiguous)}; |
346 | | - if (!actualTreatAsContiguous && dummyNeedsContiguity) { |
347 | | - setCopyIn(); |
348 | | - // Cannot do copy-out for vector subscripts: there could be repeated |
349 | | - // indices, for example |
350 | | - if (!actualHasVectorSubscript) { |
351 | | - setCopyOut(); |
352 | | - } |
353 | | - return; |
354 | | - } |
355 | | - |
356 | | - bool dummyIsAssumedShape{dummyObj->type.attrs().test( |
357 | | - characteristics::TypeAndShape::Attr::AssumedShape)}; |
358 | | - bool actualIsAssumedShape{IsAssumedShape(actual)}; |
359 | | - if ((actualIsAssumedRank && dummyIsAssumedRank) || |
360 | | - (actualIsAssumedShape && dummyIsAssumedShape)) { |
361 | | - // Assumed-rank and assumed-shape arrays are represented by descriptors, |
362 | | - // so don't need to do polymorphic check. |
363 | | - } else if (!dummyObj->ignoreTKR.test(common::IgnoreTKR::Type)) { |
364 | | - // flang supports limited cases of passing polymorphic to non-polimorphic. |
365 | | - // These cases require temporary of non-polymorphic type. (For example, |
366 | | - // the actual argument could be polymorphic array of child type, |
367 | | - // while the dummy argument could be non-polymorphic array of parent type.) |
368 | | - auto actualType{characteristics::TypeAndShape::Characterize( |
369 | | - actual, sc.foldingContext())}; |
370 | | - bool actualIsPolymorphic{actualType->type().IsPolymorphic()}; |
371 | | - if (actualIsPolymorphic && !dummyIsPolymorphic) { |
372 | | - setCopyIn(); |
373 | | - setCopyOut(); |
374 | | - } |
375 | | - } |
376 | | -} |
377 | | - |
378 | | -void ProcedureRef::DetermineCopyInOut() { |
379 | | - if (!proc_.GetSymbol()) { |
380 | | - return; |
381 | | - } |
382 | | - // Get folding context of the call site owner |
383 | | - semantics::SemanticsContext &sc{proc_.GetSymbol()->owner().context()}; |
384 | | - FoldingContext &fc{sc.foldingContext()}; |
385 | | - auto procInfo{ |
386 | | - characteristics::Procedure::Characterize(proc_, fc, /*emitError=*/true)}; |
387 | | - if (!procInfo) { |
388 | | - return; |
389 | | - } |
390 | | - if (!procInfo->HasExplicitInterface()) { |
391 | | - for (auto &actual : arguments_) { |
392 | | - if (!actual) { |
393 | | - continue; |
394 | | - } |
395 | | - DetermineCopyInOutArgument(*procInfo, *actual, sc); |
396 | | - } |
397 | | - return; |
398 | | - } |
399 | | - // Don't change anything about actual or dummy arguments, except for |
400 | | - // computing copy-in/copy-out information. If detect something wrong with |
401 | | - // the arguments, stop processing and let semantic analysis generate the |
402 | | - // error messages. |
403 | | - size_t index{0}; |
404 | | - std::set<std::string> processedKeywords; |
405 | | - bool seenKeyword{false}; |
406 | | - for (auto &actual : arguments_) { |
407 | | - if (!actual) { |
408 | | - continue; |
409 | | - } |
410 | | - if (index >= procInfo->dummyArguments.size()) { |
411 | | - // More actual arguments than dummy arguments. Semantic analysis will |
412 | | - // deal with the error. |
413 | | - return; |
414 | | - } |
415 | | - if (actual->keyword()) { |
416 | | - seenKeyword = true; |
417 | | - auto actualName{actual->keyword()->ToString()}; |
418 | | - if (processedKeywords.find(actualName) != processedKeywords.end()) { |
419 | | - // Actual arguments with duplicate keywords. Semantic analysis will |
420 | | - // deal with the error. |
421 | | - return; |
422 | | - } else { |
423 | | - processedKeywords.insert(actualName); |
424 | | - if (auto it{std::find_if(procInfo->dummyArguments.begin(), |
425 | | - procInfo->dummyArguments.end(), |
426 | | - [&](const characteristics::DummyArgument &dummy) { |
427 | | - return dummy.name == actualName; |
428 | | - })}; |
429 | | - it != procInfo->dummyArguments.end()) { |
430 | | - DetermineCopyInOutArgument(*procInfo, *actual, *it, sc); |
431 | | - } |
432 | | - } |
433 | | - } else if (seenKeyword) { |
434 | | - // Non-keyword actual argument after have seen at least one keyword |
435 | | - // actual argument. Semantic analysis will deal with the error. |
436 | | - return; |
437 | | - } else { |
438 | | - // Positional argument processing |
439 | | - DetermineCopyInOutArgument( |
440 | | - *procInfo, *actual, procInfo->dummyArguments[index], sc); |
441 | | - } |
442 | | - ++index; |
443 | | - } |
444 | | -} |
445 | | - |
446 | 250 | } // namespace Fortran::evaluate |
0 commit comments