From 6326b098852bea51debe415a85eebd1753151cd0 Mon Sep 17 00:00:00 2001 From: Haojian Wu Date: Mon, 14 Dec 2020 08:45:13 +0100 Subject: [PATCH] [AST][RecoveryExpr] Preserve type for broken overrload member call expr. Reviewed By: sammccall Differential Revision: https://reviews.llvm.org/D80109 --- clang/lib/Sema/SemaOverload.cpp | 20 ++++++++++---------- clang/test/AST/ast-dump-recovery.cpp | 8 ++++++++ .../dcl.dcl/basic.namespace/namespace.udecl/p12.cpp | 10 +++++----- 3 files changed, 23 insertions(+), 15 deletions(-) diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp index 5689efe..13d2125 100644 --- a/clang/lib/Sema/SemaOverload.cpp +++ b/clang/lib/Sema/SemaOverload.cpp @@ -14300,6 +14300,7 @@ ExprResult Sema::BuildCallToMemberFunction(Scope *S, Expr *MemExprE, UnbridgedCasts.restore(); OverloadCandidateSet::iterator Best; + bool Succeeded = false; switch (CandidateSet.BestViableFunction(*this, UnresExpr->getBeginLoc(), Best)) { case OR_Success: @@ -14307,7 +14308,7 @@ ExprResult Sema::BuildCallToMemberFunction(Scope *S, Expr *MemExprE, 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 @@ ExprResult Sema::BuildCallToMemberFunction(Scope *S, Expr *MemExprE, // 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 @@ ExprResult Sema::BuildCallToMemberFunction(Scope *S, Expr *MemExprE, 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( PartialDiagnosticAt(UnresExpr->getMemberLoc(), 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) + return BuildRecoveryExpr(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 index 2a8346e..a8da2b8 100644 --- a/clang/test/AST/ast-dump-recovery.cpp +++ b/clang/test/AST/ast-dump-recovery.cpp @@ -125,6 +125,9 @@ struct Foo2 { double func(); class ForwardClass; ForwardClass createFwd(); + + int overload(); + int overload(int, int); }; void test2(Foo2 f) { // CHECK: RecoveryExpr {{.*}} 'double' @@ -136,6 +139,11 @@ void test2(Foo2 f) { // 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 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 index ce43720..f12e008 100644 --- 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 @@ namespace test3 { 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'}} } } -- 2.7.4