diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp --- a/clang/lib/Sema/SemaOverload.cpp +++ b/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, &Best)); MemExprE = FixOverloadedFunctionReference(MemExprE, FoundDecl, Method); diff --git a/clang/test/AST/ast-dump-recovery.cpp b/clang/test/AST/ast-dump-recovery.cpp --- a/clang/test/AST/ast-dump-recovery.cpp +++ b/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'