[PATCH] D37521: [Sema][Typo correction] Assertion failure in typo correction if chain of member function calls has multiple typos

Oleg Ranevskyy via Phabricator via cfe-commits cfe-commits at lists.llvm.org
Wed Sep 6 09:39:53 PDT 2017


iid_iunknown created this revision.

This is a patch proposal for PR34507.

Typo resolution can create new TypoExprs while transforming an expression. These TypoExprs are not transformed, they are present in the resulting expression and cause the `DelayedTypos.empty() && "Uncorrected typos!"` assertion failure in `clang::Sema::~Sema()`. If clang is built without assertions, these TypoExprs are not reported causing incomplete diagnostics.

The patch checks the transformed expression for new TypoExprs and, if any found, transforms the expression again until either all TypoExprs are handled or the result becomes invalid.


Repository:
  rL LLVM

https://reviews.llvm.org/D37521

Files:
  lib/Sema/SemaExprCXX.cpp
  test/Sema/typo-correction-multiple-typos.cpp


Index: test/Sema/typo-correction-multiple-typos.cpp
===================================================================
--- test/Sema/typo-correction-multiple-typos.cpp
+++ test/Sema/typo-correction-multiple-typos.cpp
@@ -0,0 +1,41 @@
+// RUN: %clang_cc1 -fsyntax-only -verify %s
+
+// This file contains typo correction test which ensures that
+// multiple typos in a single member calls chain are correctly
+// diagnosed.
+
+class X
+{
+public:
+  void foo() const;  // expected-note {{'foo' declared here}}
+};
+
+class Y
+{
+public:
+  const X& getX() const { return m_x; } // expected-note {{'getX' declared here}}
+  int getN() const { return m_n; }
+private:
+  X m_x;
+  int m_n;
+};
+
+class Z
+{
+public:
+  const Y& getY0() const { return m_y0; } // expected-note {{'getY0' declared here}}
+  const Y& getY1() const { return m_y1; }
+
+private:
+  Y m_y0;
+  Y m_y1;
+};
+
+Z z_obj;
+
+void test()
+{
+  z_obj.getY2(). // expected-error {{no member named 'getY2' in 'Z'; did you mean 'getY0'}}
+    getM().      // expected-error {{no member named 'getM' in 'Y'; did you mean 'getX'}}
+    foe();       // expected-error {{no member named 'foe' in 'X'; did you mean 'foo'}}
+}
Index: lib/Sema/SemaExprCXX.cpp
===================================================================
--- lib/Sema/SemaExprCXX.cpp
+++ lib/Sema/SemaExprCXX.cpp
@@ -7362,6 +7362,30 @@
         break;
     }
 
+    // The transform is able to produce new TypoExprs while resolving the typos.
+    // These new TypoExprs are not resolved by the transform, they do not get
+    // into the TypoExprs container and are not reported, so they need to be
+    // handled separately.
+    // If the transform result is valid and contains newly created TypoExprs,
+    // transform the result expression again until no new TypoExprs get created
+    // or the result becomes an invalid expression. Return the longest valid
+    // expression to report as many typos as possible.
+    if (!Res.isInvalid()) {
+      while (true) {
+        unsigned TyposCount = TypoExprs.size();
+        FindTypoExprs(TypoExprs).TraverseStmt(Res.get());
+        if (TypoExprs.size() == TyposCount)
+          // No new TypoExprs created by the transform
+          break;
+        ExprResult TmpRes = TryTransform(Res.get());
+        if (TmpRes.isInvalid())
+          // Further transform prodices an invalid Expr.
+          // Stop with the last valid result.
+          break;
+        Res = TmpRes;
+      }
+    }
+
     // Ensure none of the TypoExprs have multiple typo correction candidates
     // with the same edit length that pass all the checks and filters.
     // TODO: Properly handle various permutations of possible corrections when


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D37521.114022.patch
Type: text/x-patch
Size: 2785 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20170906/c6c958dd/attachment.bin>


More information about the cfe-commits mailing list