The attached patch fixes PR21925. I think the proximate cause of the crash
is this code in CorrectDelayedTyposInExpr:
auto TyposResolved = DelayedTypos.size();
auto Result = TransformTypos(*this, Filter).Transform(E);
TyposResolved -= DelayedTypos.size();
if (TyposResolved) {
ExprEvalContexts.back().NumTypos -= TyposResolved;
return Result;
}
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.
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).
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.
Nick
Index: lib/Sema/SemaExprCXX.cpp
===================================================================
--- lib/Sema/SemaExprCXX.cpp (revision 224291)
+++ lib/Sema/SemaExprCXX.cpp (working copy)
@@ -6208,10 +6208,11 @@
auto TyposResolved = DelayedTypos.size();
auto Result = TransformTypos(*this, Filter).Transform(E);
TyposResolved -= DelayedTypos.size();
- if (TyposResolved) {
+ if (Result.get() != E) {
ExprEvalContexts.back().NumTypos -= TyposResolved;
return Result;
}
+ assert(TyposResolved == 0 && "Corrected typo but got same Expr back?");
}
return E;
}
Index: test/SemaCXX/typo-correction-delayed.cpp
===================================================================
--- test/SemaCXX/typo-correction-delayed.cpp (revision 224291)
+++ test/SemaCXX/typo-correction-delayed.cpp (working copy)
@@ -130,3 +130,16 @@
// expected-error@+1 {{use of undeclared identifier 'resulta'; did you mean 'result'?}}
Overload(resulta);
}
+
+namespace PR21925 {
+struct X {
+ int get() { return 7; } // expected-note {{'get' declared here}}
+};
+void test() {
+ X variable; // expected-note {{'variable' declared here}}
+
+ // expected-error@+2 {{use of undeclared identifier 'variableX'; did you mean 'variable'?}}
+ // expected-error@+1 {{no member named 'getX' in 'PR21925::X'; did you mean 'get'?}}
+ int x = variableX.getX();
+}
+}
_______________________________________________
cfe-commits mailing list
[email protected]
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits