Improve the diagnostic experience, including adding recovery, for
changing '->' to '.' when there is no operator-> defined for a class.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@187504 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/test/SemaCXX/member-expr.cpp b/test/SemaCXX/member-expr.cpp
index 338894c..e2462aa 100644
--- a/test/SemaCXX/member-expr.cpp
+++ b/test/SemaCXX/member-expr.cpp
@@ -79,16 +79,13 @@
   };
 
   void test0(int x) {
-    x.A::foo<int>(); // expected-error {{'int' is not a structure or union}}
   }
 
   void test1(A *x) {
-    x.A::foo<int>(); // expected-error {{'test5::A *' is a pointer}}
   }
 
   void test2(A &x) {
-    x->A::foo<int>(); // expected-error {{'test5::A' is not a pointer}} \
-                      // expected-note {{did you mean to use '.' instead?}}
+    x->A::foo<int>(); // expected-error {{'test5::A' is not a pointer; maybe you meant to use '.'?}}
   }
 }
 
@@ -182,7 +179,36 @@
 
   int f() {
     Cl0 c;
-    return c->a;  // expected-error {{member reference type 'PR15045::Cl0' is not a pointer}} \
-                  // expected-note {{did you mean to use '.' instead?}}
+    return c->a;  // expected-error {{member reference type 'PR15045::Cl0' is not a pointer; maybe you meant to use '.'?}}
+  }
+
+  struct bar {
+    void func();  // expected-note {{'func' declared here}}
+  };
+
+  struct foo {
+    bar operator->();  // expected-note 2 {{'->' applied to return value of the operator->() declared here}}
+  };
+
+  template <class T> void call_func(T t) {
+    t->func();  // expected-error-re 2 {{member reference type 'PR15045::bar' is not a pointer$}} \
+                // expected-note {{did you mean to use '.' instead?}}
+  }
+
+  void test_arrow_on_non_pointer_records() {
+    bar e;
+    foo f;
+
+    // Show that recovery has happened by also triggering typo correction
+    e->Func();  // expected-error {{member reference type 'PR15045::bar' is not a pointer; maybe you meant to use '.'?}} \
+                // expected-error {{no member named 'Func' in 'PR15045::bar'; did you mean 'func'?}}
+
+    // Make sure a fixit isn't given in the case that the '->' isn't actually
+    // the problem (the problem is with the return value of an operator->).
+    f->func();  // expected-error-re {{member reference type 'PR15045::bar' is not a pointer$}}
+
+    call_func(e);  // expected-note {{in instantiation of function template specialization 'PR15045::call_func<PR15045::bar>' requested here}}
+
+    call_func(f);  // expected-note {{in instantiation of function template specialization 'PR15045::call_func<PR15045::foo>' requested here}}
   }
 }