diff --git a/clang/lib/Sema/SemaCoroutine.cpp b/clang/lib/Sema/SemaCoroutine.cpp --- a/clang/lib/Sema/SemaCoroutine.cpp +++ b/clang/lib/Sema/SemaCoroutine.cpp @@ -861,7 +861,7 @@ auto *RD = Promise->getType()->getAsCXXRecordDecl(); if (lookupMember(*this, "await_transform", RD, Loc)) { ExprResult R = buildPromiseCall(*this, Promise, Loc, "await_transform", E); - if (R.isInvalid()) { + if (R.isInvalid() || R.get()->containsErrors()) { Diag(Loc, diag::note_coroutine_promise_implicit_await_transform_required_here) << E->getSourceRange(); 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 @@ -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 ExprError(); + break; case OR_Deleted: CandidateSet.NoteCandidates( @@ -14283,8 +14283,14 @@ PDiag(diag::err_ovl_deleted_member_call) << DeclName << MemExprE->getSourceRange()), *this, OCD_AllCandidates, Args); - // FIXME: Leaking incoming expressions! - return ExprError(); + break; + } + // Overload resolution fails, try to recover. + if (!Succeeded) { + std::vector SubExprs = {MemExprE}; + llvm::for_each(Args, [&SubExprs](Expr *E) { SubExprs.push_back(E); }); + return CreateRecoveryExpr(MemExprE->getBeginLoc(), RParenLoc, SubExprs, + 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 @@ -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' diff --git a/clang/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p12.cpp b/clang/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p12.cpp --- a/clang/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p12.cpp +++ b/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'}} } }