FuncDeclaration *hasIdentityOpAssign(AggregateDeclaration *ad, Scope *sc) { Dsymbol *assign = search_function(ad, Id::assign); if (assign) { /* check identity opAssign exists */ Expression *er = new NullExp(ad->loc, ad->type); // dummy rvalue Expression *el = new IdentifierExp(ad->loc, Id::p); // dummy lvalue el->type = ad->type; Expressions *a = new Expressions(); a->setDim(1); FuncDeclaration *f = NULL; unsigned errors = global.startGagging(); // Do not report errors, even if the unsigned oldspec = global.speculativeGag; // template opAssign fbody makes it. global.speculativeGag = global.gag; sc = sc->push(); sc->speculative = true; for (size_t i = 0; i < 2; i++) { (*a)[0] = (i == 0 ? er : el); f = resolveFuncCall(ad->loc, sc, assign, NULL, ad->type, a, 1); if (f) break; } sc = sc->pop(); global.speculativeGag = oldspec; global.endGagging(errors); if (f) { if (f->errors) return NULL; int varargs; Parameters *fparams = f->getParameters(&varargs); if (fparams->dim >= 1) { Parameter *arg0 = Parameter::getNth(fparams, 0); if (arg0->type->toDsymbol(NULL) != ad) f = NULL; } } // BUGS: This detection mechanism cannot find some opAssign-s like follows: // struct S { void opAssign(ref immutable S) const; } return f; } return NULL; }
FuncDeclaration *AggregateDeclaration::hasIdentityOpAssign(Scope *sc, Dsymbol *assign) { if (assign) { /* check identity opAssign exists */ Expression *er = new NullExp(loc, type); // dummy rvalue Expression *el = new IdentifierExp(loc, Id::p); // dummy lvalue el->type = type; Expressions ar; ar.push(er); Expressions al; al.push(el); FuncDeclaration *f = NULL; unsigned errors = global.startGagging(); // Do not report errors, even if the unsigned oldspec = global.speculativeGag; // template opAssign fbody makes it. global.speculativeGag = global.gag; sc = sc->push(); sc->speculative = true; f = resolveFuncCall(loc, sc, assign, NULL, er, &ar, 1); if (!f) f = resolveFuncCall(loc, sc, assign, NULL, er, &al, 1); sc = sc->pop(); global.speculativeGag = oldspec; global.endGagging(errors); if (f) { int varargs; Parameters *fparams = f->getParameters(&varargs); if (fparams->dim >= 1) { Parameter *arg0 = Parameter::getNth(fparams, 0); if (arg0->type->toDsymbol(NULL) != this) f = NULL; } } // BUGS: This detection mechanism cannot find some opAssign-s like follows: // struct S { void opAssign(ref immutable S) const; } return f; } return NULL; }