https://github.com/ojhunt updated https://github.com/llvm/llvm-project/pull/211705
>From f8357566dde882ef967c7cf5383ecd2785e08859 Mon Sep 17 00:00:00 2001 From: Oliver Hunt <[email protected]> Date: Thu, 23 Jul 2026 18:14:07 -0700 Subject: [PATCH] [clang][sema] Call expressions are constructed for undeduced deleted functions (#208488) The deleted function path of overload resolution always constructed a CallExpr node for the called function even if the function could not be deduced. This case is handled in other paths by DiagnoseUseOfDecl which does perform that test. The delete path cannot use that path though, as DiagnoseUseOfDecl rejects deleted functions, and the entire point of this code is to permit the continued evaluation of code even if the resolved function was deleted. To fix this we now manually check for a complete type before continuing to construct a potentially bogus CallExpr. --- clang/lib/Sema/SemaOverload.cpp | 4 ++ .../SemaCXX/deduced-return-type-cxx14.cpp | 3 ++ .../deleted-function-deduction-failure.cpp | 49 +++++++++++++++++++ 3 files changed, 56 insertions(+) create mode 100644 clang/test/SemaCXX/deleted-function-deduction-failure.cpp diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp index d66dea0d918fa..d79d4b1721b27 100644 --- a/clang/lib/Sema/SemaOverload.cpp +++ b/clang/lib/Sema/SemaOverload.cpp @@ -15027,6 +15027,10 @@ static ExprResult FinishOverloadedCallExpr(Sema &SemaRef, Scope *S, Expr *Fn, Fn->getSourceRange(), ULE->getName(), *CandidateSet, FDecl, Args); + if (completeFunctionType(SemaRef, FDecl, Fn->getBeginLoc(), + /*Complain=*/true)) + return ExprError(); + // We emitted an error for the unavailable/deleted function call but keep // the call in the AST. ExprResult Res = diff --git a/clang/test/SemaCXX/deduced-return-type-cxx14.cpp b/clang/test/SemaCXX/deduced-return-type-cxx14.cpp index 10ea9e82f5327..1bcce2fe958bc 100644 --- a/clang/test/SemaCXX/deduced-return-type-cxx14.cpp +++ b/clang/test/SemaCXX/deduced-return-type-cxx14.cpp @@ -359,7 +359,10 @@ namespace NoReturn { auto *g() {} // expected-error {{cannot deduce return type 'auto *' for function with no return statements}} auto h() = delete; // expected-note {{explicitly deleted}} + // expected-note@-1 {{'h' declared here}} + auto x = h(); // expected-error {{call to deleted}} + // expected-error@-1 {{function 'h' with deduced return type cannot be used before it is defined}} } namespace UseBeforeComplete { diff --git a/clang/test/SemaCXX/deleted-function-deduction-failure.cpp b/clang/test/SemaCXX/deleted-function-deduction-failure.cpp new file mode 100644 index 0000000000000..7a50a81926b70 --- /dev/null +++ b/clang/test/SemaCXX/deleted-function-deduction-failure.cpp @@ -0,0 +1,49 @@ +// RUN: %clang_cc1 -fsyntax-only -std=c++14 -verify %s +// RUN: %clang_cc1 -fsyntax-only -std=c++17 -verify %s +// RUN: %clang_cc1 -fsyntax-only -std=c++20 -verify %s + + +namespace UndeducedDeletedFunction { +auto deleted_auto() = delete; // #deleted_auto_decl +// expected-note@#deleted_auto_decl {{candidate function has been explicitly deleted}} +// expected-note@#deleted_auto_decl {{'deleted_auto' declared here}} + +auto auto_test() { + auto x = deleted_auto(); // #auto_use + // expected-error@#auto_use {{call to deleted function 'deleted_auto'}} + // expected-note@#deleted_auto_decl {{candidate function has been explicitly deleted}} + // expected-error@#auto_use {{function 'deleted_auto' with deduced return type cannot be used before it is defined}} + // expected-note@#deleted_auto_decl {{'deleted_auto' declared here}} + return x; +} + +auto decltype_auto_test() { + decltype(auto) x = deleted_auto(); // #decl_type_use + // expected-error@#decl_type_use {{call to deleted function 'deleted_auto'}} + // expected-note@#deleted_auto_decl {{candidate function has been explicitly deleted}} + // expected-error@#decl_type_use {{function 'deleted_auto' with deduced return type cannot be used before it is defined}} + // expected-note@#deleted_auto_decl {{'deleted_auto' declared here}} + return x; +} + +auto decltype_auto_type_test() { + __auto_type x = deleted_auto(); // #__auto_type_use + // expected-error@#__auto_type_use {{call to deleted function 'deleted_auto'}} + // expected-error@#__auto_type_use {{function 'deleted_auto' with deduced return type cannot be used before it is defined}} + return x; +} +} + +namespace DeletedWithUnresolvedExceptionSpec { +struct X {}; + +template <typename T> void failed_exception_spec(T) noexcept(T::value) = delete; // #failed_exception_spec_declared +// expected-error@#failed_exception_spec_declared {{no member named 'value' in 'DeletedWithUnresolvedExceptionSpec::X'}} +// expected-note@#failed_exception_used {{in instantiation of exception specification for 'failed_exception_spec<DeletedWithUnresolvedExceptionSpec::X>' requested here}} + +void g() { + failed_exception_spec(X{}); // #failed_exception_used + // expected-error@#failed_exception_used {{call to deleted function 'failed_exception_spec'}} + // expected-note@#failed_exception_spec_declared {{candidate function [with T = DeletedWithUnresolvedExceptionSpec::X] has been explicitly deleted}} +} +} _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
