21
21
22
22
#include " chpl/parsing/parsing-queries.h"
23
23
#include " chpl/resolution/ResolvedVisitor.h"
24
+ #include " chpl/resolution/resolution-queries.h"
24
25
#include " chpl/resolution/resolution-types.h"
25
26
#include " chpl/resolution/scope-queries.h"
26
27
#include " chpl/uast/all-uast.h"
@@ -404,13 +405,34 @@ bool VarScopeVisitor::enter(const FnCall* callAst, RV& rv) {
404
405
actualAsts.insert (actualAsts.begin (), nullptr );
405
406
}
406
407
408
+
407
409
// compute a vector indicating which actuals are passed to
408
410
// an 'out' formal in all return intent overloads
411
+ const PromotionIteratorType* promoCtx = nullptr ;
412
+ if (!rr->type ().isUnknownOrErroneous ()) {
413
+ promoCtx = rr->type ().type ()->toPromotionIteratorType ();
414
+ }
409
415
std::vector<QualifiedType> actualFormalTypes;
410
416
std::vector<Qualifier> actualFormalIntents;
417
+ std::vector<bool > actualPromoted;
411
418
computeActualFormalIntents (context, candidates, ci, actualAsts,
412
- actualFormalIntents, actualFormalTypes);
413
-
419
+ actualFormalIntents, actualFormalTypes,
420
+ actualPromoted, promoCtx);
421
+
422
+ // for a given actual index, returns:
423
+ // * nullptr if no promotion ocurred
424
+ // * the scalar type of the given actual was used in promotion
425
+ // * the actual type itself if it was not
426
+ // This can be used to signal to handleInFormal() etc. to adjust
427
+ // their behavior for promotion, and to provide the additional information
428
+ // of the scalar type.
429
+ auto getScalarType = [&](int idx) {
430
+ auto & actualQt = ci.actual (idx).type ();
431
+ return
432
+ promoCtx == nullptr ? nullptr :
433
+ actualPromoted[idx] ? &getPromotionType (context, actualQt) :
434
+ &actualQt;
435
+ };
414
436
int actualIdx = 0 ;
415
437
for (auto actual : ci.actuals ()) {
416
438
(void ) actual; // avoid compilation error about unused variable
@@ -428,11 +450,12 @@ bool VarScopeVisitor::enter(const FnCall* callAst, RV& rv) {
428
450
!(ci.name () == " init" && actualIdx == 0 )) {
429
451
// don't do this for the 'this' argument to 'init', because it
430
452
// is not getting copied.
453
+
431
454
handleInFormal (callAst, actualAst,
432
- actualFormalTypes[actualIdx], rv);
455
+ actualFormalTypes[actualIdx], getScalarType (actualIdx), rv);
433
456
} else if (kind == Qualifier::INOUT) {
434
457
handleInoutFormal (callAst, actualAst,
435
- actualFormalTypes[actualIdx], rv);
458
+ actualFormalTypes[actualIdx], getScalarType (actualIdx), rv);
436
459
} else {
437
460
// otherwise, visit the actuals to gather mentions
438
461
actualAst->traverse (rv);
@@ -576,13 +599,17 @@ computeActualFormalIntents(Context* context,
576
599
const CallInfo& ci,
577
600
const std::vector<const AstNode*>& actualAsts,
578
601
std::vector<Qualifier>& actualFormalIntents,
579
- std::vector<QualifiedType>& actualFormalTypes) {
602
+ std::vector<QualifiedType>& actualFormalTypes,
603
+ std::vector<bool >& actualPromoted,
604
+ const types::PromotionIteratorType* promoCtx) {
580
605
581
606
int nActuals = ci.numActuals ();
582
607
actualFormalIntents.clear ();
583
608
actualFormalIntents.resize (nActuals);
584
609
actualFormalTypes.clear ();
585
610
actualFormalTypes.resize (nActuals);
611
+ actualPromoted.clear ();
612
+ actualPromoted.resize (nActuals);
586
613
587
614
int nFns = candidates.numBest ();
588
615
if (nFns == 0 ) {
@@ -599,6 +626,12 @@ computeActualFormalIntents(Context* context,
599
626
auto intent = normalizeFormalIntent (fa->formalType ().kind ());
600
627
QualifiedType& aft = actualFormalTypes[actualIdx];
601
628
629
+ // all actualPromoted are guaranteed to be the same IF all the
630
+ // formal types are guaranteed to be the same, which they are
631
+ // using the checks below.
632
+ actualPromoted[actualIdx] =
633
+ promoCtx && promoCtx->promotedFormals ().count (fa->formal ()->id ()) > 0 ;
634
+
602
635
if (firstCandidate) {
603
636
actualFormalIntents[actualIdx] = intent;
604
637
if (intent != Qualifier::UNKNOWN) {
0 commit comments