[PATCH] D80109: [AST][RecoveryExpr] Preserve type for broken member call expr.

2020-12-13 Thread Haojian Wu via Phabricator via cfe-commits
This revision was landed with ongoing or failed builds.
This revision was automatically updated to reflect the committed changes.
Closed by commit rG6326b098852b: [AST][RecoveryExpr] Preserve type for broken 
overrload member call expr. (authored by hokein).

Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D80109/new/

https://reviews.llvm.org/D80109

Files:
  clang/lib/Sema/SemaOverload.cpp
  clang/test/AST/ast-dump-recovery.cpp
  clang/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p12.cpp

Index: clang/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p12.cpp
===
--- clang/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p12.cpp
+++ clang/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p12.cpp
@@ -9,7 +9,7 @@
 //   parameter types in a base class (rather than conflicting).
 
 template  struct Opaque {};
-template  void expect(Opaque _) {}
+template  void expect(Opaque _) {} // expected-note 4 {{candidate function template not viable}}
 
 // PR5727
 // This just shouldn't crash.
@@ -134,14 +134,14 @@
   void test() {
 expect<0>(Base().foo());
 expect<1>(Base().foo<0>());
-expect<0>(Derived1().foo()); // expected-error {{no matching member function for call to 'foo'}}
+expect<0>(Derived1().foo()); // expected-error {{no matching member function for call to 'foo'}} expected-error {{no matching function for call to 'expect'}}
 expect<2>(Derived1().foo<0>());
-expect<0>(Derived2().foo()); // expected-error {{no matching member function for call to 'foo'}}
+expect<0>(Derived2().foo()); // expected-error {{no matching member function for call to 'foo'}} expected-error {{no matching function for call to 'expect'}}
 expect<2>(Derived2().foo<0>());
 expect<3>(Derived3().foo());
-expect<1>(Derived3().foo<0>()); // expected-error {{no matching member function for call to 'foo'}}
+expect<1>(Derived3().foo<0>()); // expected-error {{no matching member function for call to 'foo'}} expected-error {{no matching function for call to 'expect'}}
 expect<3>(Derived4().foo());
-expect<1>(Derived4().foo<0>()); // expected-error {{no matching member function for call to 'foo'}}
+expect<1>(Derived4().foo<0>()); // expected-error {{no matching member function for call to 'foo'}} expected-error {{no matching function for call to 'expect'}}
   }
 }
 
Index: clang/test/AST/ast-dump-recovery.cpp
===
--- clang/test/AST/ast-dump-recovery.cpp
+++ clang/test/AST/ast-dump-recovery.cpp
@@ -125,6 +125,9 @@
   double func();
   class ForwardClass;
   ForwardClass createFwd();
+
+  int overload();
+  int overload(int, int);
 };
 void test2(Foo2 f) {
   // CHECK:  RecoveryExpr {{.*}} 'double'
@@ -136,6 +139,11 @@
   // CHECK-NEXT: `-MemberExpr {{.*}} '' .createFwd
   // CHECK-NEXT:   `-DeclRefExpr {{.*}} 'f'
   f.createFwd();
+  // CHECK:  RecoveryExpr {{.*}} 'int' contains-errors
+  // CHECK-NEXT: |-UnresolvedMemberExpr
+  // CHECK-NEXT:`-DeclRefExpr {{.*}} 'Foo2'
+  // CHECK-NEXT: `-IntegerLiteral {{.*}} 'int' 1
+  f.overload(1);
 }
 
 // CHECK: |-AlignedAttr {{.*}} alignas
Index: clang/lib/Sema/SemaOverload.cpp
===
--- clang/lib/Sema/SemaOverload.cpp
+++ clang/lib/Sema/SemaOverload.cpp
@@ -14300,6 +14300,7 @@
 UnbridgedCasts.restore();
 
 OverloadCandidateSet::iterator Best;
+bool Succeeded = false;
 switch (CandidateSet.BestViableFunction(*this, UnresExpr->getBeginLoc(),
 Best)) {
 case OR_Success:
@@ -14307,7 +14308,7 @@
   FoundDecl = Best->FoundDecl;
   CheckUnresolvedMemberAccess(UnresExpr, Best->FoundDecl);
   if (DiagnoseUseOfDecl(Best->FoundDecl, UnresExpr->getNameLoc()))
-return ExprError();
+break;
   // If FoundDecl is different from Method (such as if one is a template
   // and the other a specialization), make sure DiagnoseUseOfDecl is
   // called on both.
@@ -14316,7 +14317,8 @@
   // being used.
   if (Method != FoundDecl.getDecl() &&
   DiagnoseUseOfDecl(Method, UnresExpr->getNameLoc()))
-return ExprError();
+break;
+  Succeeded = true;
   break;
 
 case OR_No_Viable_Function:
@@ -14326,27 +14328,25 @@
   PDiag(diag::err_ovl_no_viable_member_function_in_call)
   << DeclName << MemExprE->getSourceRange()),
   *this, OCD_AllCandidates, Args);
-  // FIXME: Leaking incoming expressions!
-  return ExprError();
-
+  break;
 case OR_Ambiguous:
   CandidateSet.NoteCandidates(
   PartialDiagnosticAt(UnresExpr->getMemberLoc(),
   PDiag(diag::err_ovl_ambiguous_member_call)
   << DeclName << MemExprE->getSourceRange()),
   *this, 

[PATCH] D80109: [AST][RecoveryExpr] Preserve type for broken member call expr.

2020-12-11 Thread Haojian Wu via Phabricator via cfe-commits
hokein updated this revision to Diff 311148.
hokein added a comment.

rebase


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D80109/new/

https://reviews.llvm.org/D80109

Files:
  clang/lib/Sema/SemaOverload.cpp
  clang/test/AST/ast-dump-recovery.cpp
  clang/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p12.cpp

Index: clang/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p12.cpp
===
--- clang/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p12.cpp
+++ clang/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p12.cpp
@@ -9,7 +9,7 @@
 //   parameter types in a base class (rather than conflicting).
 
 template  struct Opaque {};
-template  void expect(Opaque _) {}
+template  void expect(Opaque _) {} // expected-note 4 {{candidate function template not viable}}
 
 // PR5727
 // This just shouldn't crash.
@@ -134,14 +134,14 @@
   void test() {
 expect<0>(Base().foo());
 expect<1>(Base().foo<0>());
-expect<0>(Derived1().foo()); // expected-error {{no matching member function for call to 'foo'}}
+expect<0>(Derived1().foo()); // expected-error {{no matching member function for call to 'foo'}} expected-error {{no matching function for call to 'expect'}}
 expect<2>(Derived1().foo<0>());
-expect<0>(Derived2().foo()); // expected-error {{no matching member function for call to 'foo'}}
+expect<0>(Derived2().foo()); // expected-error {{no matching member function for call to 'foo'}} expected-error {{no matching function for call to 'expect'}}
 expect<2>(Derived2().foo<0>());
 expect<3>(Derived3().foo());
-expect<1>(Derived3().foo<0>()); // expected-error {{no matching member function for call to 'foo'}}
+expect<1>(Derived3().foo<0>()); // expected-error {{no matching member function for call to 'foo'}} expected-error {{no matching function for call to 'expect'}}
 expect<3>(Derived4().foo());
-expect<1>(Derived4().foo<0>()); // expected-error {{no matching member function for call to 'foo'}}
+expect<1>(Derived4().foo<0>()); // expected-error {{no matching member function for call to 'foo'}} expected-error {{no matching function for call to 'expect'}}
   }
 }
 
Index: clang/test/AST/ast-dump-recovery.cpp
===
--- clang/test/AST/ast-dump-recovery.cpp
+++ clang/test/AST/ast-dump-recovery.cpp
@@ -125,6 +125,9 @@
   double func();
   class ForwardClass;
   ForwardClass createFwd();
+
+  int overload();
+  int overload(int, int);
 };
 void test2(Foo2 f) {
   // CHECK:  RecoveryExpr {{.*}} 'double'
@@ -136,6 +139,11 @@
   // CHECK-NEXT: `-MemberExpr {{.*}} '' .createFwd
   // CHECK-NEXT:   `-DeclRefExpr {{.*}} 'f'
   f.createFwd();
+  // CHECK:  RecoveryExpr {{.*}} 'int' contains-errors
+  // CHECK-NEXT: |-UnresolvedMemberExpr
+  // CHECK-NEXT:`-DeclRefExpr {{.*}} 'Foo2'
+  // CHECK-NEXT: `-IntegerLiteral {{.*}} 'int' 1
+  f.overload(1);
 }
 
 // CHECK: |-AlignedAttr {{.*}} alignas
Index: clang/lib/Sema/SemaOverload.cpp
===
--- clang/lib/Sema/SemaOverload.cpp
+++ clang/lib/Sema/SemaOverload.cpp
@@ -14300,6 +14300,7 @@
 UnbridgedCasts.restore();
 
 OverloadCandidateSet::iterator Best;
+bool Succeeded = false;
 switch (CandidateSet.BestViableFunction(*this, UnresExpr->getBeginLoc(),
 Best)) {
 case OR_Success:
@@ -14307,7 +14308,7 @@
   FoundDecl = Best->FoundDecl;
   CheckUnresolvedMemberAccess(UnresExpr, Best->FoundDecl);
   if (DiagnoseUseOfDecl(Best->FoundDecl, UnresExpr->getNameLoc()))
-return ExprError();
+break;
   // If FoundDecl is different from Method (such as if one is a template
   // and the other a specialization), make sure DiagnoseUseOfDecl is
   // called on both.
@@ -14316,7 +14317,8 @@
   // being used.
   if (Method != FoundDecl.getDecl() &&
   DiagnoseUseOfDecl(Method, UnresExpr->getNameLoc()))
-return ExprError();
+break;
+  Succeeded = true;
   break;
 
 case OR_No_Viable_Function:
@@ -14326,27 +14328,25 @@
   PDiag(diag::err_ovl_no_viable_member_function_in_call)
   << DeclName << MemExprE->getSourceRange()),
   *this, OCD_AllCandidates, Args);
-  // FIXME: Leaking incoming expressions!
-  return ExprError();
-
+  break;
 case OR_Ambiguous:
   CandidateSet.NoteCandidates(
   PartialDiagnosticAt(UnresExpr->getMemberLoc(),
   PDiag(diag::err_ovl_ambiguous_member_call)
   << DeclName << MemExprE->getSourceRange()),
   *this, OCD_AmbiguousCandidates, Args);
-  // FIXME: Leaking incoming expressions!
-  return ExprError();
-
+  break;
 case OR_Deleted:
   CandidateSet.NoteCandidates(
   

[PATCH] D80109: [AST][RecoveryExpr] Preserve type for broken member call expr.

2020-11-30 Thread Haojian Wu via Phabricator via cfe-commits
hokein marked 2 inline comments as done.
hokein added a comment.

sorry for the delay, picking it up now.




Comment at: clang/lib/Sema/SemaCoroutine.cpp:864
 ExprResult R = buildPromiseCall(*this, Promise, Loc, "await_transform", E);
-if (R.isInvalid()) {
+if (R.isInvalid() || R.get()->containsErrors()) {
   Diag(Loc,

we need this change to prevent a regression on co_await-range-for.

without this change, we will emit 2 `call to deleted member function 
'await_transform'` diagnostics  on 
https://github.com/llvm/llvm-project/blob/master/clang/test/SemaCXX/co_await-range-for.cpp#L52-L54.



Comment at: clang/test/AST/ast-dump-recovery.cpp:123
+
+  // FIXME: capture the type!
+  f.func(1);

sammccall wrote:
> why does this not work?
> isn't there only one candidate, so chooseRecoveryType should pick it?
this is on a different codepath, will fix in https://reviews.llvm.org/D92298


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D80109/new/

https://reviews.llvm.org/D80109

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D80109: [AST][RecoveryExpr] Preserve type for broken member call expr.

2020-11-29 Thread Haojian Wu via Phabricator via cfe-commits
hokein updated this revision to Diff 308267.
hokein added a comment.
Herald added a subscriber: lxfind.

rebase and address comments.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D80109/new/

https://reviews.llvm.org/D80109

Files:
  clang/lib/Sema/SemaCoroutine.cpp
  clang/lib/Sema/SemaOverload.cpp
  clang/test/AST/ast-dump-recovery.cpp
  clang/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p12.cpp

Index: clang/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p12.cpp
===
--- clang/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p12.cpp
+++ clang/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p12.cpp
@@ -9,7 +9,7 @@
 //   parameter types in a base class (rather than conflicting).
 
 template  struct Opaque {};
-template  void expect(Opaque _) {}
+template  void expect(Opaque _) {} // expected-note 4 {{candidate function template not viable}}
 
 // PR5727
 // This just shouldn't crash.
@@ -134,14 +134,14 @@
   void test() {
 expect<0>(Base().foo());
 expect<1>(Base().foo<0>());
-expect<0>(Derived1().foo()); // expected-error {{no matching member function for call to 'foo'}}
+expect<0>(Derived1().foo()); // expected-error {{no matching member function for call to 'foo'}} expected-error {{no matching function for call to 'expect'}}
 expect<2>(Derived1().foo<0>());
-expect<0>(Derived2().foo()); // expected-error {{no matching member function for call to 'foo'}}
+expect<0>(Derived2().foo()); // expected-error {{no matching member function for call to 'foo'}} expected-error {{no matching function for call to 'expect'}}
 expect<2>(Derived2().foo<0>());
 expect<3>(Derived3().foo());
-expect<1>(Derived3().foo<0>()); // expected-error {{no matching member function for call to 'foo'}}
+expect<1>(Derived3().foo<0>()); // expected-error {{no matching member function for call to 'foo'}} expected-error {{no matching function for call to 'expect'}}
 expect<3>(Derived4().foo());
-expect<1>(Derived4().foo<0>()); // expected-error {{no matching member function for call to 'foo'}}
+expect<1>(Derived4().foo<0>()); // expected-error {{no matching member function for call to 'foo'}} expected-error {{no matching function for call to 'expect'}}
   }
 }
 
Index: clang/test/AST/ast-dump-recovery.cpp
===
--- clang/test/AST/ast-dump-recovery.cpp
+++ clang/test/AST/ast-dump-recovery.cpp
@@ -121,6 +121,21 @@
   foo->func(x);
 }
 
+// CHECK:  FunctionDecl {{.*}} test2
+// CHECK-NEXT: |-ParmVarDecl {{.*}} f
+// CHECK-NEXT: `-CompoundStmt
+// CHECK-NEXT:-RecoveryExpr {{.*}} 'int' contains-errors
+// CHECK-NEXT:|-UnresolvedMemberExpr
+// CHECK-NEXT:   `-DeclRefExpr {{.*}} 'Foo2'
+// CHECK-NEXT:`-IntegerLiteral {{.*}} 'int' 1
+struct Foo2 {
+  int overload();
+  int overload(int, int);
+};
+void test2(Foo2 f) {
+  f.overload(1); // verify "int" is preserved
+}
+
 // CHECK: |-AlignedAttr {{.*}} alignas
 // CHECK-NEXT:| `-RecoveryExpr {{.*}} contains-errors
 // CHECK-NEXT:|   `-UnresolvedLookupExpr {{.*}} 'invalid'
Index: clang/lib/Sema/SemaOverload.cpp
===
--- clang/lib/Sema/SemaOverload.cpp
+++ clang/lib/Sema/SemaOverload.cpp
@@ -14239,6 +14239,7 @@
 UnbridgedCasts.restore();
 
 OverloadCandidateSet::iterator Best;
+bool Succeeded = false;
 switch (CandidateSet.BestViableFunction(*this, UnresExpr->getBeginLoc(),
 Best)) {
 case OR_Success:
@@ -14246,7 +14247,7 @@
   FoundDecl = Best->FoundDecl;
   CheckUnresolvedMemberAccess(UnresExpr, Best->FoundDecl);
   if (DiagnoseUseOfDecl(Best->FoundDecl, UnresExpr->getNameLoc()))
-return ExprError();
+break;
   // If FoundDecl is different from Method (such as if one is a template
   // and the other a specialization), make sure DiagnoseUseOfDecl is
   // called on both.
@@ -14255,7 +14256,8 @@
   // being used.
   if (Method != FoundDecl.getDecl() &&
   DiagnoseUseOfDecl(Method, UnresExpr->getNameLoc()))
-return ExprError();
+break;
+  Succeeded = true;
   break;
 
 case OR_No_Viable_Function:
@@ -14265,8 +14267,7 @@
   PDiag(diag::err_ovl_no_viable_member_function_in_call)
   << DeclName << MemExprE->getSourceRange()),
   *this, OCD_AllCandidates, Args);
-  // FIXME: Leaking incoming expressions!
-  return ExprError();
+  break;
 
 case OR_Ambiguous:
   CandidateSet.NoteCandidates(
@@ -14274,8 +14275,7 @@
   PDiag(diag::err_ovl_ambiguous_member_call)
   << DeclName << MemExprE->getSourceRange()),
   *this, OCD_AmbiguousCandidates, Args);
-  // FIXME: Leaking incoming expressions!
-  return 

[PATCH] D80109: [AST][RecoveryExpr] Preserve type for broken member call expr.

2020-09-18 Thread Sam McCall via Phabricator via cfe-commits
sammccall added a comment.

@hokein Did this get landed at some point?


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D80109/new/

https://reviews.llvm.org/D80109

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D80109: [AST][RecoveryExpr] Preserve type for broken member call expr.

2020-05-18 Thread Sam McCall via Phabricator via cfe-commits
sammccall accepted this revision.
sammccall added inline comments.
This revision is now accepted and ready to land.



Comment at: clang/lib/Sema/SemaOverload.cpp:14083
 OverloadCandidateSet::iterator Best;
+bool Succeeded = true;
 switch (CandidateSet.BestViableFunction(*this, UnresExpr->getBeginLoc(),

seems like `bool Success = false` would be a "safer" default and have to be set 
in fewer places



Comment at: clang/lib/Sema/SemaOverload.cpp:14105
 
 case OR_No_Viable_Function:
   CandidateSet.NoteCandidates(

hokein wrote:
> It is a bit sad that the broken function call cases (too many/few agguments) 
> are failing into this group, all candidates are not viable -- this means we 
> don't get any benefits (no `Best`), for some cases, it is suboptimal even 
> though the best candidate looks like obvious.
> 
> ```
> class Collection {
>   const char *find(int) const;
>   char* find(int);
> };
> void test1(const Collection ) {
>  C.find(); // we want const char*, but all overloads are not viable and 
> return types are not the same, so no type captured here.
> }
> ```
Yeah, at some point we can add more heuristics (discard non-viable or hidden 
functions using heuristics) to handle this case, like I did in 
SemaCodeComplete...



Comment at: clang/lib/Sema/SemaOverload.cpp:14133
 }
+// Overload resolvation fails, try to recover.
+if (!Succeeded)

resolvation -> resolution



Comment at: clang/test/AST/ast-dump-recovery.cpp:123
+
+  // FIXME: capture the type!
+  f.func(1);

why does this not work?
isn't there only one candidate, so chooseRecoveryType should pick it?


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D80109/new/

https://reviews.llvm.org/D80109



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D80109: [AST][RecoveryExpr] Preserve type for broken member call expr.

2020-05-18 Thread Haojian Wu via Phabricator via cfe-commits
hokein marked an inline comment as done.
hokein added inline comments.



Comment at: clang/lib/Sema/SemaOverload.cpp:14105
 
 case OR_No_Viable_Function:
   CandidateSet.NoteCandidates(

It is a bit sad that the broken function call cases (too many/few agguments) 
are failing into this group, all candidates are not viable -- this means we 
don't get any benefits (no `Best`), for some cases, it is suboptimal even 
though the best candidate looks like obvious.

```
class Collection {
  const char *find(int) const;
  char* find(int);
};
void test1(const Collection ) {
 C.find(); // we want const char*, but all overloads are not viable and return 
types are not the same, so no type captured here.
}
```


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D80109/new/

https://reviews.llvm.org/D80109



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D80109: [AST][RecoveryExpr] Preserve type for broken member call expr.

2020-05-18 Thread Haojian Wu via Phabricator via cfe-commits
hokein created this revision.
hokein added a reviewer: sammccall.
Herald added a project: clang.

Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D80109

Files:
  clang/lib/Sema/SemaOverload.cpp
  clang/test/AST/ast-dump-recovery.cpp

Index: clang/test/AST/ast-dump-recovery.cpp
===
--- clang/test/AST/ast-dump-recovery.cpp
+++ clang/test/AST/ast-dump-recovery.cpp
@@ -101,6 +101,29 @@
   foo->func(x);
 }
 
+// CHECK:  FunctionDecl {{.*}} test2
+// CHECK-NEXT: |-ParmVarDecl {{.*}} f
+// CHECK-NEXT: `-CompoundStmt
+// CHECK-NEXT:   |-RecoveryExpr {{.*}} 'int' contains-errors
+// CHECK-NEXT: `-UnresolvedMemberExpr
+// CHECK-NEXT:   `-DeclRefExpr {{.*}} 'Foo2'
+// CHECK-NEXT:   `-RecoveryExpr {{.*}} ''
+// CHECK-NEXT: |-MemberExpr {{.*}} ''
+// CHECK-NEXT: | `-DeclRefExpr {{.*}}
+// CHECK-NEXT:   `-IntegerLiteral {{.*}} 'int' 1
+struct Foo2 {
+  int overload(int);
+  int overload(int, int);
+
+  double func();
+};
+void test2(Foo2 f) {
+  f.overload(); // verify "int" is preserved
+
+  // FIXME: capture the type!
+  f.func(1);
+}
+
 // CHECK: |-AlignedAttr {{.*}} alignas
 // CHECK-NEXT:| `-RecoveryExpr {{.*}} contains-errors
 // CHECK-NEXT:|   `-UnresolvedLookupExpr {{.*}} 'invalid'
Index: clang/lib/Sema/SemaOverload.cpp
===
--- clang/lib/Sema/SemaOverload.cpp
+++ clang/lib/Sema/SemaOverload.cpp
@@ -14080,14 +14080,17 @@
 UnbridgedCasts.restore();
 
 OverloadCandidateSet::iterator Best;
+bool Succeeded = true;
 switch (CandidateSet.BestViableFunction(*this, UnresExpr->getBeginLoc(),
 Best)) {
 case OR_Success:
   Method = cast(Best->Function);
   FoundDecl = Best->FoundDecl;
   CheckUnresolvedMemberAccess(UnresExpr, Best->FoundDecl);
-  if (DiagnoseUseOfDecl(Best->FoundDecl, UnresExpr->getNameLoc()))
-return ExprError();
+  if (DiagnoseUseOfDecl(Best->FoundDecl, UnresExpr->getNameLoc())) {
+Succeeded = false;
+break;
+  }
   // If FoundDecl is different from Method (such as if one is a template
   // and the other a specialization), make sure DiagnoseUseOfDecl is
   // called on both.
@@ -14096,7 +14099,7 @@
   // being used.
   if (Method != FoundDecl.getDecl() &&
   DiagnoseUseOfDecl(Method, UnresExpr->getNameLoc()))
-return ExprError();
+Succeeded = false;
   break;
 
 case OR_No_Viable_Function:
@@ -14106,8 +14109,8 @@
   PDiag(diag::err_ovl_no_viable_member_function_in_call)
   << DeclName << MemExprE->getSourceRange()),
   *this, OCD_AllCandidates, Args);
-  // FIXME: Leaking incoming expressions!
-  return ExprError();
+  Succeeded = false;
+  break;
 
 case OR_Ambiguous:
   CandidateSet.NoteCandidates(
@@ -14115,8 +14118,8 @@
   PDiag(diag::err_ovl_ambiguous_member_call)
   << DeclName << MemExprE->getSourceRange()),
   *this, OCD_AmbiguousCandidates, Args);
-  // FIXME: Leaking incoming expressions!
-  return ExprError();
+  Succeeded = false;
+  break;
 
 case OR_Deleted:
   CandidateSet.NoteCandidates(
@@ -14124,9 +14127,14 @@
   PDiag(diag::err_ovl_deleted_member_call)
   << DeclName << MemExprE->getSourceRange()),
   *this, OCD_AllCandidates, Args);
-  // FIXME: Leaking incoming expressions!
-  return ExprError();
+  Succeeded = false;
+  break;
 }
+// Overload resolvation fails, try to recover.
+if (!Succeeded)
+  return CreateRecoveryExpr(MemExprE->getBeginLoc(), MemExprE->getEndLoc(),
+{MemExprE},
+chooseRecoveryType(CandidateSet, ));
 
 MemExprE = FixOverloadedFunctionReference(MemExprE, FoundDecl, Method);
 
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits