compiler/resolution/functionResolution.cpp
// Check to ensure the actual supplied to an OUT, INOUT or REF argument
// is an lvalue.
Check to ensure the actual supplied to an OUT, INOUT or REF argument
is an lvalue.
Check to ensure the actual supplied to an OUT INOUT or REF argument is an lvalue .
for_formals_actuals(formal, actual, call) {
    bool errorMsg = false;
    switch (formal->intent) {
     case INTENT_BLANK:
     case INTENT_CONST:
     case INTENT_PARAM:
     case INTENT_TYPE:
     case INTENT_REF_MAYBE_CONST:
      break;
     case INTENT_IN:
     case INTENT_CONST_IN:
      if (formal->getValType()->symbol->hasFlag(FLAG_COPY_MUTATES))
        if (!isLegalLvalueActualArg(formal, actual))
          errorMsg = true;
      break;
     case INTENT_INOUT:
     case INTENT_OUT:
     case INTENT_REF:
      if (!isLegalLvalueActualArg(formal, actual))
        errorMsg = true;
      break;
     case INTENT_CONST_REF:
      if (!isLegalConstRefActualArg(formal, actual))
        errorMsg = true;
      break;
     default:
      INT_ASSERT(false);
      break;
    }
    FnSymbol* nonTaskFnParent = NULL;
    if (errorMsg &&
        checkAndUpdateIfLegalFieldOfThis(call, actual, nonTaskFnParent)) {
      errorMsg = false;
      nonTaskFnParent->addFlag(FLAG_MODIFIES_CONST_FIELDS);
    }
    if (errorMsg == true) {
      if (nonTaskFnParent &&
          nonTaskFnParent->hasFlag(FLAG_SUPPRESS_LVALUE_ERRORS)) {
        return;
      }
      if (SymExpr* se = toSymExpr(actual)) {
        if (se->symbol()->hasFlag(FLAG_SUPPRESS_LVALUE_ERRORS)) {
          return;
        }
      }
      FnSymbol* calleeFn = call->resolvedFunction();
      INT_ASSERT(calleeFn == formal->defPoint->parentSymbol); 
      Symbol* actSym = isSymExpr(actual) ? toSymExpr(actual)->symbol() : NULL;
      bool isInitParam = actSym->hasFlag(FLAG_PARAM) && calleeFn->isInitializer();
      if (calleeFn->hasFlag(FLAG_ASSIGNOP)) {
        INT_ASSERT(callStack.n > 0 && callStack.v[callStack.n - 1] == call);
        FnSymbol*   fnParent   = toFnSymbol(call->parentSymbol);
        const char* recordName = defaultRecordAssignmentTo(fnParent);
        if (recordName && callStack.n >= 2) {
          USR_FATAL_CONT(callStack.v[callStack.n - 2],
                         "cannot assign to a record of the type %s using "
                         "the default assignment operator because it has "
                         "'const' field(s)",
                         recordName);
        } else {
          USR_FATAL_CONT(actual, "illegal lvalue in assignment");
        }
      } else if (isInitParam == false) {
        ModuleSymbol* mod          = calleeFn->getModule();
        char          cn1          = calleeFn->name[0];
        const char*   calleeParens = (isalpha(cn1) || cn1 == '_') ? "()" : "";
        if (developer || mod->modTag == MOD_USER) {
          USR_FATAL_CONT(actual,
                         "non-lvalue actual is passed to %s formal '%s' "
                         "of %s%s",
                         formal->intentDescrString(),
                         formal->name,
                         calleeFn->name,
                         calleeParens);
        } else {
          USR_FATAL_CONT(actual,
                         "non-lvalue actual is passed to a %s formal of "
                         "%s%s",
                         formal->intentDescrString(),
                         calleeFn->name,
                         calleeParens);
        }
      }
      if (SymExpr* aSE = toSymExpr(actual)) {
        Symbol* aVar = aSE->symbol();
        if (aVar->hasFlag(FLAG_CONST_DUE_TO_TASK_FORALL_INTENT)) {
          printTaskOrForallConstErrorNote(aVar);
        }
      }
    }
  }
for_formals_actuals ( formal , actual , call ) { bool errorMsg = false ; switch ( formal -> intent ) { case INTENT_BLANK : case INTENT_CONST : case INTENT_PARAM : case INTENT_TYPE : case INTENT_REF_MAYBE_CONST : break ; case INTENT_IN : case INTENT_CONST_IN : if ( formal -> getValType ( ) -> symbol -> hasFlag ( FLAG_COPY_MUTATES ) ) if ( ! isLegalLvalueActualArg ( formal , actual ) ) errorMsg = true ; break ; case INTENT_INOUT : case INTENT_OUT : case INTENT_REF : if ( ! isLegalLvalueActualArg ( formal , actual ) ) errorMsg = true ; break ; case INTENT_CONST_REF : if ( ! isLegalConstRefActualArg ( formal , actual ) ) errorMsg = true ; break ; default : INT_ASSERT ( false ) ; break ; } FnSymbol * nonTaskFnParent = NULL ; if ( errorMsg && checkAndUpdateIfLegalFieldOfThis ( call , actual , nonTaskFnParent ) ) { errorMsg = false ; nonTaskFnParent -> addFlag ( FLAG_MODIFIES_CONST_FIELDS ) ; } if ( errorMsg == true ) { if ( nonTaskFnParent && nonTaskFnParent -> hasFlag ( FLAG_SUPPRESS_LVALUE_ERRORS ) ) { return ; } if ( SymExpr * se = toSymExpr ( actual ) ) { if ( se -> symbol ( ) -> hasFlag ( FLAG_SUPPRESS_LVALUE_ERRORS ) ) { return ; } } FnSymbol * calleeFn = call -> resolvedFunction ( ) ; INT_ASSERT ( calleeFn == formal -> defPoint -> parentSymbol ) ; Symbol * actSym = isSymExpr ( actual ) ? toSymExpr ( actual ) -> symbol ( ) : NULL ; bool isInitParam = actSym -> hasFlag ( FLAG_PARAM ) && calleeFn -> isInitializer ( ) ; if ( calleeFn -> hasFlag ( FLAG_ASSIGNOP ) ) { INT_ASSERT ( callStack . n > 0 && callStack . v [ callStack . n - 1 ] == call ) ; FnSymbol * fnParent = toFnSymbol ( call -> parentSymbol ) ; const char * recordName = defaultRecordAssignmentTo ( fnParent ) ; if ( recordName && callStack . n >= 2 ) { USR_FATAL_CONT ( callStack . v [ callStack . n - 2 ] , " " " " " " , recordName ) ; } else { USR_FATAL_CONT ( actual , " " ) ; } } else if ( isInitParam == false ) { ModuleSymbol * mod = calleeFn -> getModule ( ) ; char cn1 = calleeFn -> name [ 0 ] ; const char * calleeParens = ( isalpha ( cn1 ) || cn1 == ' ' ) ? " " : " " ; if ( developer || mod -> modTag == MOD_USER ) { USR_FATAL_CONT ( actual , " " " " , formal -> intentDescrString ( ) , formal -> name , calleeFn -> name , calleeParens ) ; } else { USR_FATAL_CONT ( actual , " " " " , formal -> intentDescrString ( ) , calleeFn -> name , calleeParens ) ; } } if ( SymExpr * aSE = toSymExpr ( actual ) ) { Symbol * aVar = aSE -> symbol ( ) ; if ( aVar -> hasFlag ( FLAG_CONST_DUE_TO_TASK_FORALL_INTENT ) ) { printTaskOrForallConstErrorNote ( aVar ) ; } } } }
Check to ensure the actual supplied to an OUT, INOUT or REF argument
is an lvalue.
Check to ensure the actual supplied to an OUT INOUT or REF argument is an lvalue .
// not checking them here // generally, not checking them here // but, FLAG_COPY_MUTATES makes INTENT_IN actually modify actual // all intents should be covered above // sets nonTaskFnParent // we are asked to ignore errors here // Ignore lvalue errors default argument expressions // sanity // This assert is FYI. Perhaps can remove it if it fails. // blame on the caller of the caller, if available // Should this be the same condition as in insertLineNumber() ?