<div dir="ltr">The attached patch fixes PR21925. I think the proximate cause of the crash is this code in CorrectDelayedTyposInExpr:<div><br></div><div><div>    auto TyposResolved = DelayedTypos.size();</div><div>    auto Result = TransformTypos(*this, Filter).Transform(E);</div><div>    TyposResolved -= DelayedTypos.size();</div><div>    if (TyposResolved) {</div><div>      ExprEvalContexts.back().NumTypos -= TyposResolved;</div><div>      return Result;</div><div>    }</div></div><div><br></div><div>When TransformTypos visits the member expression, it converts "typoA.typoB()" into "notypo.typoB()" and produces a new TypoExpr for typoB. I'm not certain whether TransformTypos ought to be creating new TypoExprs at all, but if it does then we see "DelayedTypos.size()" is 1 before and 1 after, so we end up returning the original expression instead of the transformed one. We'll then try to visit it again later and the assertion fires as we try to type-correct "typoA" again.</div><div><br></div><div>My proposed fix is to check whether the resulting expr is the same after transformation. There's might be two problems here. Is it possible that a subexpr was modified in place instead of being replaced? If so we'll accidentally throw away the correction. Also, what should we do if the new ExprResult is invalid? Currently we ignore the "invalid bit" and just look at the pointer it contains (in my experiments I see a 0x1 on an invalid return from TransformTypos which doesn't equal E so we propagate that invalid along).</div><div><br></div><div>But my higher-level question is why we only built one delayed TypoExpr and then created another one part way through transforming it? Is it just that delaying resolution of member-expr typos hasn't been implemented yet? I would expected to see some form of dependent member expr with two typo exprs on either side, then work through the possibilities with the streaming consumer interface.</div><div><br></div><div>Nick</div><div><br></div></div>