@@ -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,121 @@ 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 (contextSymbol.inNonRoot)
10494+ return ;
10495+
10496+ if (attributeSource is null )
10497+ attributeSource = contextSymbol;
10498+
10499+ Identifier usingOp = attributeSource is contextSymbol ? Id.opUDAOn : Id.opChildOfUDAOn;
10500+
10501+ void handle (Expression expr)
10502+ {
10503+ Objects* tiobjects = new Objects;
10504+ tiobjects.push(contextSymbol);
10505+
10506+ auto dtie = new DotTemplateInstanceExp(contextSymbol.loc, expr, usingOp, tiobjects);
10507+ expr = dtie.expressionSemantic(sc);
10508+
10509+ if (auto dve = expr.isDotVarExp)
10510+ {
10511+ if (dve.var.isFuncDeclaration)
10512+ {
10513+ expr = new CallExp(contextSymbol.loc, expr);
10514+ expr = expr.expressionSemantic(sc);
10515+ expr = ctfeInterpret(expr);
10516+ }
10517+ }
10518+ }
10519+
10520+ void handleType (TypeExp te)
10521+ {
10522+ if (auto ts = te.type.isTypeStruct)
10523+ {
10524+ if (ts.sym is null )
10525+ return ;
10526+
10527+ Dsymbol dsym2 = search_function(ts.sym, usingOp);
10528+ if (dsym2 is null )
10529+ return ;
10530+
10531+ handle(new DotIdExp (te.loc, te, Id._init));
10532+ }
10533+ }
10534+
10535+ void handleStructLiteral (StructLiteralExp sle)
10536+ {
10537+ Dsymbol dsym2 = search_function(sle.sd, usingOp);
10538+ if (dsym2 is null )
10539+ return ;
10540+
10541+ handle(sle);
10542+ }
10543+
10544+ void dispatch (Expression expr) {
10545+ if (auto sle = expr.isStructLiteralExp)
10546+ handleStructLiteral(sle);
10547+ else if (auto te = expr.isTypeExp)
10548+ handleType(te);
10549+ }
10550+
10551+ if (auto vd = attributeSource.isVarDeclaration)
10552+ {
10553+ if (vd.needThis)
10554+ return ; // This will trigger dual-context.
10555+ }
10556+
10557+ if (auto attrs = attributeSource.userAttribDecl())
10558+ {
10559+ foreach (attr2; * attrs.atts)
10560+ {
10561+ if (auto te = attr2.isTupleExp)
10562+ {
10563+ // te.e0 should be null here
10564+
10565+ if (te.exps is null )
10566+ continue ;
10567+
10568+ foreach (attr3; * te.exps)
10569+ dispatch(attr3);
10570+ }
10571+ else
10572+ dispatch(attr2);
10573+ }
10574+ }
10575+ }
10576+
10577+ void symbolForOpChildOfUDAOn (ClassDeclaration cd, Scope* sc, ClassDeclaration contextSymbol = null )
10578+ {
10579+ if (cd.baseclasses is null )
10580+ return ;
10581+
10582+ if (contextSymbol is null )
10583+ contextSymbol = cd;
10584+
10585+ if (contextSymbol.inNonRoot)
10586+ return ;
10587+
10588+ // Okay this may not make much sense.
10589+ // On a class declaration the base classes include both interfaces and classes,
10590+ // but they won't be normalized to include all parents.
10591+ // Instead we first check the base classes list,
10592+ // and then for each of the interfaces that they inherit we go ahead and see both it, and its parents.
10593+
10594+ foreach (base; * cd.baseclasses)
10595+ {
10596+ symbolForOpUDAOn(contextSymbol, sc, base.sym);
10597+
10598+ foreach (ref bi; base.baseInterfaces)
10599+ {
10600+ symbolForOpUDAOn(contextSymbol, sc, bi.sym);
10601+ symbolForOpChildOfUDAOn(bi.sym, sc, contextSymbol);
10602+ }
10603+ }
10604+ }
0 commit comments