diff --git a/clang/include/clang/Basic/DiagnosticASTKinds.td b/clang/include/clang/Basic/DiagnosticASTKinds.td --- a/clang/include/clang/Basic/DiagnosticASTKinds.td +++ b/clang/include/clang/Basic/DiagnosticASTKinds.td @@ -597,4 +597,11 @@ def warn_unaligned_access : Warning< "field %1 within %0 is less aligned than %2 and is usually due to %0 being " "packed, which can lead to unaligned accesses">, InGroup, DefaultIgnore; + +def err_unsupported_destructor_overloading : Error< + "overloading destructors is not supported yet in this version. Consult " + "'https://github.com/llvm/llvm-project/issues/45614' for updates">; +def note_unsupported_destructor_overloading_declaration : Note< + "destructor declared here.">; + } diff --git a/clang/lib/AST/DeclCXX.cpp b/clang/lib/AST/DeclCXX.cpp --- a/clang/lib/AST/DeclCXX.cpp +++ b/clang/lib/AST/DeclCXX.cpp @@ -29,6 +29,7 @@ #include "clang/AST/TypeLoc.h" #include "clang/AST/UnresolvedSet.h" #include "clang/Basic/Diagnostic.h" +#include "clang/Basic/DiagnosticAST.h" #include "clang/Basic/IdentifierTable.h" #include "clang/Basic/LLVM.h" #include "clang/Basic/LangOptions.h" @@ -1895,6 +1896,33 @@ DeclContext::lookup_result R = lookup(Name); + // We don't support C++20 constrained destructors yet, and we are unlikely to + // do so in the near future. Until we do, we check here for multiple + // declarations and report an error. We have to handle correctly the case of + // merged declarations in modules and the case of invalid templated + // destructors so this is a bit involved. + // We also don't emit errors on OpenCL code because OpenCL desturctors can + // overload on address space (https://reviews.llvm.org/D64569). + if (!(R.empty() || R.isSingleResult()) && !Context.getLangOpts().OpenCL) { + bool hasNonTrivialOverloads = false; + auto firstDecl = R.front(); + for (const auto &decl : R) { + if (!decl->isTemplateDecl() && !firstDecl->isTemplateDecl() && + !Context.isSameEntity(decl, firstDecl)) { + hasNonTrivialOverloads = true; + } + } + if (hasNonTrivialOverloads) { + Context.getDiagnostics().Report( + getLocation(), diag::err_unsupported_destructor_overloading); + for (const auto &decl : R) { + Context.getDiagnostics().Report( + decl->getLocation(), + diag::note_unsupported_destructor_overloading_declaration); + } + } + } + return R.empty() ? nullptr : dyn_cast(R.front()); } diff --git a/clang/test/CXX/over/over.match/over.match.viable/p3.cpp b/clang/test/CXX/over/over.match/over.match.viable/p3.cpp --- a/clang/test/CXX/over/over.match/over.match.viable/p3.cpp +++ b/clang/test/CXX/over/over.match/over.match.viable/p3.cpp @@ -44,24 +44,26 @@ template struct S { + // expected-error@-1 7{{overloading destructors is not supported}} void foo(int) requires false; void foo(A) requires true; S(A) requires false; S(double) requires true; ~S() requires false; // expected-note@-1 2{{because 'false' evaluated to false}} + // expected-note@-2 7{{destructor declared here}} ~S() requires true; + // expected-note@-1 7{{destructor declared here}} operator int() requires true; operator int() requires false; }; void bar() { + // Note - we have a hard error in this case until P0848 is implemented. WrapsStatics::foo(A{}); S{1.}.foo(A{}); // expected-error@-1{{invalid reference to function '~S': constraints not satisfied}} - // Note - this behavior w.r.t. constrained dtors is a consequence of current - // wording, which does not invoke overload resolution when a dtor is called. - // P0848 is set to address this issue. + S s = 1; // expected-error@-1{{invalid reference to function '~S': constraints not satisfied}} int a = s;