// find a caller (direct or not) that is not in a task function, // for line number reporting static FnSymbol* findNonTaskCaller(FnSymbol* fn) { FnSymbol* retval = NULL; if (fn == NULL || fn->inTree() == false) { retval = fn; } else { while (retval == NULL) { if (isTaskFun(fn) == false) { retval = fn; } else { FnSymbol* caller = NULL; forv_Vec(CallExpr, call, gCallExprs) { if (call->inTree() == true) { if (FnSymbol* cfn = call->resolvedFunction()) { if (cfn == fn) { caller = toFnSymbol(call->parentSymbol); break; } } } } if (caller == NULL) { retval = fn; } else { fn = caller; } } } } return retval; }
static void markImplicitThrows(FnSymbol* fn, std::set<FnSymbol*>* visited, implicitThrowsReasons_t* reasons) { // Currently, only task functions and if-exprs can be implicitly throws. if (!isTaskFun(fn)) return; // If we already visited this function, don't visit it again. if (visited->count(fn) > 0) return; // Add to visited set first thing to prevent infinite recursion // if there ever is a cycle of calls. visited->insert(fn); ImplicitThrowsVisitor visit(visited, reasons); // Note that this function can recurse because // the ImplicitThrowsVisitor will call markImplicitThrows. fn->body->accept(&visit); if (visit.throws()) { // Update the reasons - for printing out error messages with // the user view of no task functions (say) (*reasons)[fn] = visit.reason(); fn->throwsErrorInit(); // If we only are throwing because of calls to functions marked // with FLAG_UNCHECKED_THROWS, this function should also be // so marked. if (visit.unchecked()) fn->addFlag(FLAG_UNCHECKED_THROWS); } }
forv_Vec(FnSymbol, fn, nestedFunctions) { FnSymbol* curFn = fn; while (curFn && isTaskFun(curFn)) { curFn = toFnSymbol(curFn->defPoint->parentSymbol); } // Now curFn is NULL or the first not-a-task function if (curFn && curFn->isIterator()) { // Mark all of the inner task functions IteratorInfo* ii = curFn->iteratorInfo; curFn = fn; while (curFn && isTaskFun(curFn)) { curFn->addFlag(FLAG_TASK_FN_FROM_ITERATOR_FN); curFn->iteratorInfo = ii; curFn = toFnSymbol(curFn->defPoint->parentSymbol); } } }
virtual bool enterCallExpr(CallExpr* node) { if (node->isPrimitive(PRIM_YIELD)) { expandYield(this, node); } else if (FnSymbol* calledFn = node->resolvedFunction()) { if (isTaskFun(calledFn)) { expandTaskFn(this, node, calledFn); } else if (calledFn == gChplPropagateError) { handleChplPropagateErrorCall(node); } } // There shouldn't be anything interesting inside the call. // expandTaskFn() takes care of descending into 'taskFn'. return false; }
// find a caller (direct or not) that is not in a task function, // for line number reporting static FnSymbol* findNonTaskCaller(FnSymbol* fn) { if (!fn || !fn->inTree()) return fn; while (true) { if (!isTaskFun(fn)) return fn; // who calls this? FnSymbol* caller = NULL; forv_Vec(CallExpr, call, gCallExprs) { if (call->inTree()) { if (FnSymbol* cfn = call->isResolved()) { if (cfn == fn) { caller = toFnSymbol(call->parentSymbol); break; } } } } if (!caller) return fn; // or should it return the original value of 'fn'? fn = caller; } }