@@ -3435,6 +3435,8 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
34353435
34363436 dsym.semanticRun = PASS .semanticdone;
34373437
3438+ symbolForOpUDAOn(dsym, sc);
3439+
34383440 if (dsym.type.toBasetype().ty == Terror)
34393441 dsym.errors = true ;
34403442
@@ -5006,6 +5008,8 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
50065008 }
50075009 }
50085010
5011+ symbolForOpUDAOn(sd, sc);
5012+
50095013 if (global.errors != errors)
50105014 {
50115015 // The type is no good.
@@ -5892,6 +5896,9 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
58925896 .error(cldec.loc, " %s `%s` already exists at %s. Perhaps in another function with the same name?" , cldec.kind, cldec.toPrettyChars, cd.loc.toChars());
58935897 }
58945898
5899+ symbolForOpUDAOn(cldec, sc);
5900+ symbolForOpChildOfUDAOn(cldec, sc);
5901+
58955902 if (global.errors != errors || (cldec.baseClass && cldec.baseClass.errors))
58965903 {
58975904 // The type is no good, but we should keep the
@@ -6216,6 +6223,9 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
62166223
62176224 sc2.pop();
62186225
6226+ symbolForOpUDAOn(idec, sc);
6227+ symbolForOpChildOfUDAOn(idec, sc);
6228+
62196229 if (global.errors != errors)
62206230 {
62216231 // The type is no good.
@@ -10474,3 +10484,115 @@ extern (D) bool oneMembers(Dsymbols* members, out Dsymbol ps, Identifier ident)
1047410484 // printf("\ttrue\n");
1047510485 return true ;
1047610486}
10487+
10488+ // Should be private, but is public due to
10489+ void symbolForOpUDAOn (Dsymbol contextSymbol, Scope* sc, Dsymbol attributeSource=null )
10490+ {
10491+ import dmd.opover : search_function;
10492+
10493+ if (attributeSource is null )
10494+ attributeSource = contextSymbol;
10495+
10496+ Identifier usingOp = attributeSource is contextSymbol ? Id.opUDAOn : Id.opChildOfUDAOn;
10497+
10498+ void handle (Expression expr)
10499+ {
10500+ Objects* tiobjects = new Objects;
10501+ tiobjects.push(contextSymbol);
10502+
10503+ auto dtie = new DotTemplateInstanceExp(contextSymbol.loc, expr, usingOp, tiobjects);
10504+ expr = dtie.expressionSemantic(sc);
10505+
10506+ if (auto dve = expr.isDotVarExp)
10507+ {
10508+ if (dve.var.isFuncDeclaration)
10509+ {
10510+ expr = new CallExp(contextSymbol.loc, expr);
10511+ expr = expr.expressionSemantic(sc);
10512+ expr = ctfeInterpret(expr);
10513+ }
10514+ }
10515+ }
10516+
10517+ void handleType (TypeExp te)
10518+ {
10519+ if (auto ts = te.type.isTypeStruct)
10520+ {
10521+ if (ts.sym is null )
10522+ return ;
10523+
10524+ Dsymbol dsym2 = search_function(ts.sym, usingOp);
10525+ if (dsym2 is null )
10526+ return ;
10527+
10528+ handle(new DotIdExp (te.loc, te, Id._init));
10529+ }
10530+ }
10531+
10532+ void handleStructLiteral (StructLiteralExp sle)
10533+ {
10534+ Dsymbol dsym2 = search_function(sle.sd, usingOp);
10535+ if (dsym2 is null )
10536+ return ;
10537+
10538+ handle(sle);
10539+ }
10540+
10541+ void dispatch (Expression expr) {
10542+ if (auto sle = expr.isStructLiteralExp)
10543+ handleStructLiteral(sle);
10544+ else if (auto te = expr.isTypeExp)
10545+ handleType(te);
10546+ }
10547+
10548+ if (auto vd = attributeSource.isVarDeclaration)
10549+ {
10550+ if (vd.needThis)
10551+ return ; // This will trigger dual-context.
10552+ }
10553+
10554+ if (auto attrs = attributeSource.userAttribDecl())
10555+ {
10556+ foreach (attr2; * attrs.atts)
10557+ {
10558+ if (auto te = attr2.isTupleExp)
10559+ {
10560+ // te.e0 should be null here
10561+
10562+ if (te.exps is null )
10563+ continue ;
10564+
10565+ foreach (attr3; * te.exps)
10566+ dispatch(attr3);
10567+ }
10568+ else
10569+ dispatch(attr2);
10570+ }
10571+ }
10572+ }
10573+
10574+ void symbolForOpChildOfUDAOn (ClassDeclaration cd, Scope* sc, ClassDeclaration contextSymbol = null )
10575+ {
10576+ if (cd.baseclasses is null )
10577+ return ;
10578+
10579+ if (contextSymbol is null )
10580+ contextSymbol = cd;
10581+
10582+ // Okay this may not make much sense.
10583+ // On a class declaration the base classes include both interfaces and classes,
10584+ // but they won't be normalized to include all parents.
10585+ // Instead we first check the base classes list,
10586+ // and then for each of the interfaces that they inherit we go ahead and see both it, and its parents.
10587+
10588+ foreach (base; * cd.baseclasses)
10589+ {
10590+ symbolForOpUDAOn(contextSymbol, sc, base.sym);
10591+
10592+ foreach (ref bi; base.baseInterfaces)
10593+ {
10594+ symbolForOpUDAOn(contextSymbol, sc, bi.sym);
10595+ symbolForOpChildOfUDAOn(bi.sym, sc, contextSymbol);
10596+ }
10597+ }
10598+ }
0 commit comments