void visit(CallExp *e) { //printf("CallExp(): %s\n", e->toChars()); /* Check each argument that is * passed as 'return scope'. */ Type *t1 = e->e1->type->toBasetype(); TypeFunction *tf = NULL; TypeDelegate *dg = NULL; if (t1->ty == Tdelegate) { dg = (TypeDelegate *)t1; tf = (TypeFunction *)dg->next; } else if (t1->ty == Tfunction) tf = (TypeFunction *)t1; else return; if (e->arguments && e->arguments->dim) { /* j=1 if _arguments[] is first argument, * skip it because it is not passed by ref */ size_t j = (tf->linkage == LINKd && tf->varargs == 1); for (size_t i = j; i < e->arguments->dim; ++i) { Expression *arg = (*e->arguments)[i]; size_t nparams = Parameter::dim(tf->parameters); if (i - j < nparams && i >= j) { Parameter *p = Parameter::getNth(tf->parameters, i - j); const StorageClass stc = tf->parameterStorageClass(p); if ((stc & (STCscope)) && (stc & STCreturn)) arg->accept(this); else if ((stc & (STCref)) && (stc & STCreturn)) escapeByRef(arg, er); } } } // If 'this' is returned, check it too if (e->e1->op == TOKdotvar && t1->ty == Tfunction) { DotVarExp *dve = (DotVarExp *)e->e1; FuncDeclaration *fd = dve->var->isFuncDeclaration(); AggregateDeclaration *ad = NULL; if (global.params.vsafe && tf->isreturn && fd && (ad = fd->isThis()) != NULL) { if (ad->isClassDeclaration() || tf->isscope) // this is 'return scope' dve->e1->accept(this); else if (ad->isStructDeclaration()) // this is 'return ref' escapeByRef(dve->e1, er); } else if (dve->var->storage_class & STCreturn || tf->isreturn) { if (dve->var->storage_class & STCscope) dve->e1->accept(this); else if (dve->var->storage_class & STCref) escapeByRef(dve->e1, er); } } /* If returning the result of a delegate call, the .ptr * field of the delegate must be checked. */ if (dg) { if (tf->isreturn) e->e1->accept(this); } }
void visit(CallExp *e) { /* If the function returns by ref, check each argument that is * passed as 'return ref'. */ Type *t1 = e->e1->type->toBasetype(); TypeFunction *tf; if (t1->ty == Tdelegate) tf = (TypeFunction *)((TypeDelegate *)t1)->next; else if (t1->ty == Tfunction) tf = (TypeFunction *)t1; else return; if (tf->isref) { if (e->arguments && e->arguments->dim) { /* j=1 if _arguments[] is first argument, * skip it because it is not passed by ref */ size_t j = (tf->linkage == LINKd && tf->varargs == 1); for (size_t i = j; i < e->arguments->dim; ++i) { Expression *arg = (*e->arguments)[i]; size_t nparams = Parameter::dim(tf->parameters); if (i - j < nparams && i >= j) { Parameter *p = Parameter::getNth(tf->parameters, i - j); const StorageClass stc = tf->parameterStorageClass(p); if ((stc & (STCout | STCref)) && (stc & STCreturn)) arg->accept(this); else if ((stc & STCscope) && (stc & STCreturn)) { if (arg->op == TOKdelegate) { DelegateExp *de = (DelegateExp *)arg; if (de->func->isNested()) er->byexp.push(de); } else escapeByValue(arg, er); } } } } // If 'this' is returned by ref, check it too if (e->e1->op == TOKdotvar && t1->ty == Tfunction) { DotVarExp *dve = (DotVarExp *)e->e1; if (dve->var->storage_class & STCreturn || tf->isreturn) { if ((dve->var->storage_class & STCscope) || tf->isscope) escapeByValue(dve->e1, er); else if ((dve->var->storage_class & STCref) || tf->isref) dve->e1->accept(this); } } // If it's a delegate, check it too if (e->e1->op == TOKvar && t1->ty == Tdelegate) { escapeByValue(e->e1, er); } } else er->byexp.push(e); }